summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGoldwyn Rodrigues <rgoldwyn@suse.de>2014-04-03 17:46:59 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-03 19:20:55 -0400
commit8ed6b23709b346f7bfc1edab47003a205a6a9f69 (patch)
tree61c8187bb57a42165ef838e21a268a346ab3af16
parent84d86f83f9d0e8431a3c9eae4c47e9d7ff49a411 (diff)
ocfs2: revert iput deferring code in ocfs2_drop_dentry_lock
The following patches are reverted in this patch because these patches caused performance regression in the remote unlink() calls. ea455f8ab683 - ocfs2: Push out dropping of dentry lock to ocfs2_wq f7b1aa69be13 - ocfs2: Fix deadlock on umount 5fd131893793 - ocfs2: Don't oops in ocfs2_kill_sb on a failed mount Previous patches in this series removed the possible deadlocks from downconvert thread so the above patches shouldn't be needed anymore. The regression is caused because these patches delay the iput() in case of dentry unlocks. This also delays the unlocking of the open lockres. The open lockresource is required to test if the inode can be wiped from disk or not. When the deleting node does not get the open lock, it marks it as orphan (even though it is not in use by another node/process) and causes a journal checkpoint. This delays operations following the inode eviction. This also moves the inode to the orphaned inode which further causes more I/O and a lot of unneccessary orphans. The following script can be used to generate the load causing issues: declare -a create declare -a remove declare -a iterations=(1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384) unique="`mktemp -u XXXXX`" script="/tmp/idontknow-${unique}.sh" cat <<EOF > "${script}" for n in {1..8}; do mkdir -p test/dir\${n} eval touch test/dir\${n}/foo{1.."\$1"} done EOF chmod 700 "${script}" function fcreate () { exec 2>&1 /usr/bin/time --format=%E "${script}" "$1" } function fremove () { exec 2>&1 /usr/bin/time --format=%E ssh node2 "cd `pwd`; rm -Rf test*" } function fcp () { exec 2>&1 /usr/bin/time --format=%E ssh node3 "cd `pwd`; cp -R test test.new" } echo ------------------------------------------------- echo "| # files | create #s | copy #s | remove #s |" echo ------------------------------------------------- for ((x=0; x < ${#iterations[*]} ; x++)) do create[$x]="`fcreate ${iterations[$x]}`" copy[$x]="`fcp ${iterations[$x]}`" remove[$x]="`fremove`" printf "| %8d | %9s | %9s | %9s |\n" ${iterations[$x]} ${create[$x]} ${copy[$x]} ${remove[$x]} done rm "${script}" echo "------------------------" Signed-off-by: Srinivas Eeda <srinivas.eeda@oracle.com> Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> Signed-off-by: Jan Kara <jack@suse.cz> Reviewed-by: Mark Fasheh <mfasheh@suse.de> Cc: Joel Becker <jlbec@evilplan.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/ocfs2/dcache.c61
-rw-r--r--fs/ocfs2/dcache.h12
-rw-r--r--fs/ocfs2/ocfs2.h28
-rw-r--r--fs/ocfs2/super.c30
4 files changed, 9 insertions, 122 deletions
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c
index 0d3a97d2d5f6..e2e05a106beb 100644
--- a/fs/ocfs2/dcache.c
+++ b/fs/ocfs2/dcache.c
@@ -37,7 +37,6 @@
37#include "dlmglue.h" 37#include "dlmglue.h"
38#include "file.h" 38#include "file.h"
39#include "inode.h" 39#include "inode.h"
40#include "super.h"
41#include "ocfs2_trace.h" 40#include "ocfs2_trace.h"
42 41
43void ocfs2_dentry_attach_gen(struct dentry *dentry) 42void ocfs2_dentry_attach_gen(struct dentry *dentry)
@@ -346,52 +345,6 @@ out_attach:
346 return ret; 345 return ret;
347} 346}
348 347
349DEFINE_SPINLOCK(dentry_list_lock);
350
351/* We limit the number of dentry locks to drop in one go. We have
352 * this limit so that we don't starve other users of ocfs2_wq. */
353#define DL_INODE_DROP_COUNT 64
354
355/* Drop inode references from dentry locks */
356static void __ocfs2_drop_dl_inodes(struct ocfs2_super *osb, int drop_count)
357{
358 struct ocfs2_dentry_lock *dl;
359
360 spin_lock(&dentry_list_lock);
361 while (osb->dentry_lock_list && (drop_count < 0 || drop_count--)) {
362 dl = osb->dentry_lock_list;
363 osb->dentry_lock_list = dl->dl_next;
364 spin_unlock(&dentry_list_lock);
365 iput(dl->dl_inode);
366 kfree(dl);
367 spin_lock(&dentry_list_lock);
368 }
369 spin_unlock(&dentry_list_lock);
370}
371
372void ocfs2_drop_dl_inodes(struct work_struct *work)
373{
374 struct ocfs2_super *osb = container_of(work, struct ocfs2_super,
375 dentry_lock_work);
376
377 __ocfs2_drop_dl_inodes(osb, DL_INODE_DROP_COUNT);
378 /*
379 * Don't queue dropping if umount is in progress. We flush the
380 * list in ocfs2_dismount_volume
381 */
382 spin_lock(&dentry_list_lock);
383 if (osb->dentry_lock_list &&
384 !ocfs2_test_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED))
385 queue_work(ocfs2_wq, &osb->dentry_lock_work);
386 spin_unlock(&dentry_list_lock);
387}
388
389/* Flush the whole work queue */
390void ocfs2_drop_all_dl_inodes(struct ocfs2_super *osb)
391{
392 __ocfs2_drop_dl_inodes(osb, -1);
393}
394
395/* 348/*
396 * ocfs2_dentry_iput() and friends. 349 * ocfs2_dentry_iput() and friends.
397 * 350 *
@@ -416,24 +369,16 @@ void ocfs2_drop_all_dl_inodes(struct ocfs2_super *osb)
416static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb, 369static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
417 struct ocfs2_dentry_lock *dl) 370 struct ocfs2_dentry_lock *dl)
418{ 371{
372 iput(dl->dl_inode);
419 ocfs2_simple_drop_lockres(osb, &dl->dl_lockres); 373 ocfs2_simple_drop_lockres(osb, &dl->dl_lockres);
420 ocfs2_lock_res_free(&dl->dl_lockres); 374 ocfs2_lock_res_free(&dl->dl_lockres);
421 375 kfree(dl);
422 /* We leave dropping of inode reference to ocfs2_wq as that can
423 * possibly lead to inode deletion which gets tricky */
424 spin_lock(&dentry_list_lock);
425 if (!osb->dentry_lock_list &&
426 !ocfs2_test_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED))
427 queue_work(ocfs2_wq, &osb->dentry_lock_work);
428 dl->dl_next = osb->dentry_lock_list;
429 osb->dentry_lock_list = dl;
430 spin_unlock(&dentry_list_lock);
431} 376}
432 377
433void ocfs2_dentry_lock_put(struct ocfs2_super *osb, 378void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
434 struct ocfs2_dentry_lock *dl) 379 struct ocfs2_dentry_lock *dl)
435{ 380{
436 int unlock; 381 int unlock = 0;
437 382
438 BUG_ON(dl->dl_count == 0); 383 BUG_ON(dl->dl_count == 0);
439 384
diff --git a/fs/ocfs2/dcache.h b/fs/ocfs2/dcache.h
index b79eff709958..55f58892b153 100644
--- a/fs/ocfs2/dcache.h
+++ b/fs/ocfs2/dcache.h
@@ -29,13 +29,8 @@
29extern const struct dentry_operations ocfs2_dentry_ops; 29extern const struct dentry_operations ocfs2_dentry_ops;
30 30
31struct ocfs2_dentry_lock { 31struct ocfs2_dentry_lock {
32 /* Use count of dentry lock */
33 unsigned int dl_count; 32 unsigned int dl_count;
34 union { 33 u64 dl_parent_blkno;
35 /* Linked list of dentry locks to release */
36 struct ocfs2_dentry_lock *dl_next;
37 u64 dl_parent_blkno;
38 };
39 34
40 /* 35 /*
41 * The ocfs2_dentry_lock keeps an inode reference until 36 * The ocfs2_dentry_lock keeps an inode reference until
@@ -49,14 +44,9 @@ struct ocfs2_dentry_lock {
49int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode, 44int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode,
50 u64 parent_blkno); 45 u64 parent_blkno);
51 46
52extern spinlock_t dentry_list_lock;
53
54void ocfs2_dentry_lock_put(struct ocfs2_super *osb, 47void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
55 struct ocfs2_dentry_lock *dl); 48 struct ocfs2_dentry_lock *dl);
56 49
57void ocfs2_drop_dl_inodes(struct work_struct *work);
58void ocfs2_drop_all_dl_inodes(struct ocfs2_super *osb);
59
60struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno, 50struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno,
61 int skip_unhashed); 51 int skip_unhashed);
62 52
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index 64c02239ba46..a780e20d4fba 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -275,19 +275,16 @@ enum ocfs2_mount_options
275 OCFS2_MOUNT_HB_GLOBAL = 1 << 14, /* Global heartbeat */ 275 OCFS2_MOUNT_HB_GLOBAL = 1 << 14, /* Global heartbeat */
276}; 276};
277 277
278#define OCFS2_OSB_SOFT_RO 0x0001 278#define OCFS2_OSB_SOFT_RO 0x0001
279#define OCFS2_OSB_HARD_RO 0x0002 279#define OCFS2_OSB_HARD_RO 0x0002
280#define OCFS2_OSB_ERROR_FS 0x0004 280#define OCFS2_OSB_ERROR_FS 0x0004
281#define OCFS2_OSB_DROP_DENTRY_LOCK_IMMED 0x0008 281#define OCFS2_DEFAULT_ATIME_QUANTUM 60
282
283#define OCFS2_DEFAULT_ATIME_QUANTUM 60
284 282
285struct ocfs2_journal; 283struct ocfs2_journal;
286struct ocfs2_slot_info; 284struct ocfs2_slot_info;
287struct ocfs2_recovery_map; 285struct ocfs2_recovery_map;
288struct ocfs2_replay_map; 286struct ocfs2_replay_map;
289struct ocfs2_quota_recovery; 287struct ocfs2_quota_recovery;
290struct ocfs2_dentry_lock;
291struct ocfs2_super 288struct ocfs2_super
292{ 289{
293 struct task_struct *commit_task; 290 struct task_struct *commit_task;
@@ -415,11 +412,6 @@ struct ocfs2_super
415 struct list_head blocked_lock_list; 412 struct list_head blocked_lock_list;
416 unsigned long blocked_lock_count; 413 unsigned long blocked_lock_count;
417 414
418 /* List of dentry locks to release. Anyone can add locks to
419 * the list, ocfs2_wq processes the list */
420 struct ocfs2_dentry_lock *dentry_lock_list;
421 struct work_struct dentry_lock_work;
422
423 /* List of dquot structures to drop last reference to */ 415 /* List of dquot structures to drop last reference to */
424 struct llist_head dquot_drop_list; 416 struct llist_head dquot_drop_list;
425 struct work_struct dquot_drop_work; 417 struct work_struct dquot_drop_work;
@@ -584,18 +576,6 @@ static inline void ocfs2_set_osb_flag(struct ocfs2_super *osb,
584 spin_unlock(&osb->osb_lock); 576 spin_unlock(&osb->osb_lock);
585} 577}
586 578
587
588static inline unsigned long ocfs2_test_osb_flag(struct ocfs2_super *osb,
589 unsigned long flag)
590{
591 unsigned long ret;
592
593 spin_lock(&osb->osb_lock);
594 ret = osb->osb_flags & flag;
595 spin_unlock(&osb->osb_lock);
596 return ret;
597}
598
599static inline void ocfs2_set_ro_flag(struct ocfs2_super *osb, 579static inline void ocfs2_set_ro_flag(struct ocfs2_super *osb,
600 int hard) 580 int hard)
601{ 581{
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index b800a1f78d78..888a1457af96 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -1241,30 +1241,11 @@ static struct dentry *ocfs2_mount(struct file_system_type *fs_type,
1241 return mount_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super); 1241 return mount_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super);
1242} 1242}
1243 1243
1244static void ocfs2_kill_sb(struct super_block *sb)
1245{
1246 struct ocfs2_super *osb = OCFS2_SB(sb);
1247
1248 /* Failed mount? */
1249 if (!osb || atomic_read(&osb->vol_state) == VOLUME_DISABLED)
1250 goto out;
1251
1252 /* Prevent further queueing of inode drop events */
1253 spin_lock(&dentry_list_lock);
1254 ocfs2_set_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED);
1255 spin_unlock(&dentry_list_lock);
1256 /* Wait for work to finish and/or remove it */
1257 cancel_work_sync(&osb->dentry_lock_work);
1258out:
1259 kill_block_super(sb);
1260}
1261
1262static struct file_system_type ocfs2_fs_type = { 1244static struct file_system_type ocfs2_fs_type = {
1263 .owner = THIS_MODULE, 1245 .owner = THIS_MODULE,
1264 .name = "ocfs2", 1246 .name = "ocfs2",
1265 .mount = ocfs2_mount, 1247 .mount = ocfs2_mount,
1266 .kill_sb = ocfs2_kill_sb, 1248 .kill_sb = kill_block_super,
1267
1268 .fs_flags = FS_REQUIRES_DEV|FS_RENAME_DOES_D_MOVE, 1249 .fs_flags = FS_REQUIRES_DEV|FS_RENAME_DOES_D_MOVE,
1269 .next = NULL 1250 .next = NULL
1270}; 1251};
@@ -1930,12 +1911,6 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
1930 1911
1931 debugfs_remove(osb->osb_ctxt); 1912 debugfs_remove(osb->osb_ctxt);
1932 1913
1933 /*
1934 * Flush inode dropping work queue so that deletes are
1935 * performed while the filesystem is still working
1936 */
1937 ocfs2_drop_all_dl_inodes(osb);
1938
1939 /* Orphan scan should be stopped as early as possible */ 1914 /* Orphan scan should be stopped as early as possible */
1940 ocfs2_orphan_scan_stop(osb); 1915 ocfs2_orphan_scan_stop(osb);
1941 1916
@@ -2278,9 +2253,6 @@ static int ocfs2_initialize_super(struct super_block *sb,
2278 INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery); 2253 INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery);
2279 journal->j_state = OCFS2_JOURNAL_FREE; 2254 journal->j_state = OCFS2_JOURNAL_FREE;
2280 2255
2281 INIT_WORK(&osb->dentry_lock_work, ocfs2_drop_dl_inodes);
2282 osb->dentry_lock_list = NULL;
2283
2284 INIT_WORK(&osb->dquot_drop_work, ocfs2_drop_dquot_refs); 2256 INIT_WORK(&osb->dquot_drop_work, ocfs2_drop_dquot_refs);
2285 init_llist_head(&osb->dquot_drop_list); 2257 init_llist_head(&osb->dquot_drop_list);
2286 2258