aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTao Ma <tao.ma@oracle.com>2010-08-16 04:58:21 -0400
committerJoel Becker <joel.becker@oracle.com>2010-09-10 11:56:24 -0400
commitb4d693fcc5fe99ed211addb5c6a0f8398f0b266e (patch)
treed036160f644030afb1e91f275cd62aa79d9293b2 /fs
parenta33f13efe05192e7a805018a2ce2b2afddd04057 (diff)
ocfs2: Cache system inodes of other slots.
Durring orphan scan, if we are slot 0, and we are replaying orphan_dir:0001, the general process is that for every file in this dir: 1. we will iget orphan_dir:0001, since there is no inode for it. we will have to create an inode and read it from the disk. 2. do the normal work, such as delete_inode and remove it from the dir if it is allowed. 3. call iput orphan_dir:0001 when we are done. In this case, since we have no dcache for this inode, i_count will reach 0, and VFS will have to call clear_inode and in ocfs2_clear_inode we will checkpoint the inode which will let ocfs2_cmt and journald begin to work. 4. We loop back to 1 for the next file. So you see, actually for every deleted file, we have to read the orphan dir from the disk and checkpoint the journal. It is very time consuming and cause a lot of journal checkpoint I/O. A better solution is that we can have another reference for these inodes in ocfs2_super. So if there is no other race among nodes(which will let dlmglue to checkpoint the inode), for step 3, clear_inode won't be called and for step 1, we may only need to read the inode for the 1st time. This is a big win for us. So this patch will try to cache system inodes of other slots so that we will have one more reference for these inodes and avoid the extra inode read and journal checkpoint. Signed-off-by: Tao Ma <tao.ma@oracle.com> Signed-off-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/ocfs2/ocfs2.h3
-rw-r--r--fs/ocfs2/ocfs2_fs.h5
-rw-r--r--fs/ocfs2/super.c20
-rw-r--r--fs/ocfs2/sysfile.c60
4 files changed, 73 insertions, 15 deletions
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index 65739b3b3276..687e291d73f2 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -284,7 +284,8 @@ struct ocfs2_super
284 struct super_block *sb; 284 struct super_block *sb;
285 struct inode *root_inode; 285 struct inode *root_inode;
286 struct inode *sys_root_inode; 286 struct inode *sys_root_inode;
287 struct inode *system_inodes[NUM_SYSTEM_INODES]; 287 struct inode *global_system_inodes[NUM_GLOBAL_SYSTEM_INODES];
288 struct inode **local_system_inodes;
288 289
289 struct ocfs2_slot_info *slot_info; 290 struct ocfs2_slot_info *slot_info;
290 291
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index 33f1c9a8258d..723b20dac414 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -309,6 +309,7 @@ enum {
309 USER_QUOTA_SYSTEM_INODE, 309 USER_QUOTA_SYSTEM_INODE,
310 GROUP_QUOTA_SYSTEM_INODE, 310 GROUP_QUOTA_SYSTEM_INODE,
311#define OCFS2_LAST_GLOBAL_SYSTEM_INODE GROUP_QUOTA_SYSTEM_INODE 311#define OCFS2_LAST_GLOBAL_SYSTEM_INODE GROUP_QUOTA_SYSTEM_INODE
312#define OCFS2_FIRST_LOCAL_SYSTEM_INODE ORPHAN_DIR_SYSTEM_INODE
312 ORPHAN_DIR_SYSTEM_INODE, 313 ORPHAN_DIR_SYSTEM_INODE,
313 EXTENT_ALLOC_SYSTEM_INODE, 314 EXTENT_ALLOC_SYSTEM_INODE,
314 INODE_ALLOC_SYSTEM_INODE, 315 INODE_ALLOC_SYSTEM_INODE,
@@ -317,8 +318,12 @@ enum {
317 TRUNCATE_LOG_SYSTEM_INODE, 318 TRUNCATE_LOG_SYSTEM_INODE,
318 LOCAL_USER_QUOTA_SYSTEM_INODE, 319 LOCAL_USER_QUOTA_SYSTEM_INODE,
319 LOCAL_GROUP_QUOTA_SYSTEM_INODE, 320 LOCAL_GROUP_QUOTA_SYSTEM_INODE,
321#define OCFS2_LAST_LOCAL_SYSTEM_INODE LOCAL_GROUP_QUOTA_SYSTEM_INODE
320 NUM_SYSTEM_INODES 322 NUM_SYSTEM_INODES
321}; 323};
324#define NUM_GLOBAL_SYSTEM_INODES OCFS2_LAST_GLOBAL_SYSTEM_INODE
325#define NUM_LOCAL_SYSTEM_INODES \
326 (NUM_SYSTEM_INODES - OCFS2_FIRST_LOCAL_SYSTEM_INODE)
322 327
323static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = { 328static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = {
324 /* Global system inodes (single copy) */ 329 /* Global system inodes (single copy) */
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 47415398d56a..350e8b5a9396 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -514,11 +514,11 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb)
514 514
515 mlog_entry_void(); 515 mlog_entry_void();
516 516
517 for (i = 0; i < NUM_SYSTEM_INODES; i++) { 517 for (i = 0; i < NUM_GLOBAL_SYSTEM_INODES; i++) {
518 inode = osb->system_inodes[i]; 518 inode = osb->global_system_inodes[i];
519 if (inode) { 519 if (inode) {
520 iput(inode); 520 iput(inode);
521 osb->system_inodes[i] = NULL; 521 osb->global_system_inodes[i] = NULL;
522 } 522 }
523 } 523 }
524 524
@@ -534,6 +534,20 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb)
534 osb->root_inode = NULL; 534 osb->root_inode = NULL;
535 } 535 }
536 536
537 if (!osb->local_system_inodes)
538 goto out;
539
540 for (i = 0; i < NUM_LOCAL_SYSTEM_INODES * osb->max_slots; i++) {
541 if (osb->local_system_inodes[i]) {
542 iput(osb->local_system_inodes[i]);
543 osb->local_system_inodes[i] = NULL;
544 }
545 }
546
547 kfree(osb->local_system_inodes);
548 osb->local_system_inodes = NULL;
549
550out:
537 mlog_exit(0); 551 mlog_exit(0);
538} 552}
539 553
diff --git a/fs/ocfs2/sysfile.c b/fs/ocfs2/sysfile.c
index bfe7190cdbf1..902efb23b6a6 100644
--- a/fs/ocfs2/sysfile.c
+++ b/fs/ocfs2/sysfile.c
@@ -44,11 +44,6 @@ static struct inode * _ocfs2_get_system_file_inode(struct ocfs2_super *osb,
44 int type, 44 int type,
45 u32 slot); 45 u32 slot);
46 46
47static inline int is_global_system_inode(int type);
48static inline int is_in_system_inode_array(struct ocfs2_super *osb,
49 int type,
50 u32 slot);
51
52#ifdef CONFIG_DEBUG_LOCK_ALLOC 47#ifdef CONFIG_DEBUG_LOCK_ALLOC
53static struct lock_class_key ocfs2_sysfile_cluster_lock_key[NUM_SYSTEM_INODES]; 48static struct lock_class_key ocfs2_sysfile_cluster_lock_key[NUM_SYSTEM_INODES];
54#endif 49#endif
@@ -59,11 +54,52 @@ static inline int is_global_system_inode(int type)
59 type <= OCFS2_LAST_GLOBAL_SYSTEM_INODE; 54 type <= OCFS2_LAST_GLOBAL_SYSTEM_INODE;
60} 55}
61 56
62static inline int is_in_system_inode_array(struct ocfs2_super *osb, 57static struct inode **get_local_system_inode(struct ocfs2_super *osb,
63 int type, 58 int type,
64 u32 slot) 59 u32 slot)
65{ 60{
66 return slot == osb->slot_num || is_global_system_inode(type); 61 int index;
62 struct inode **local_system_inodes, **free = NULL;
63
64 BUG_ON(slot == OCFS2_INVALID_SLOT);
65 BUG_ON(type < OCFS2_FIRST_LOCAL_SYSTEM_INODE ||
66 type > OCFS2_LAST_LOCAL_SYSTEM_INODE);
67
68 spin_lock(&osb->osb_lock);
69 local_system_inodes = osb->local_system_inodes;
70 spin_unlock(&osb->osb_lock);
71
72 if (unlikely(!local_system_inodes)) {
73 local_system_inodes = kzalloc(sizeof(struct inode *) *
74 NUM_LOCAL_SYSTEM_INODES *
75 osb->max_slots,
76 GFP_NOFS);
77 if (!local_system_inodes) {
78 mlog_errno(-ENOMEM);
79 /*
80 * return NULL here so that ocfs2_get_sytem_file_inodes
81 * will try to create an inode and use it. We will try
82 * to initialize local_system_inodes next time.
83 */
84 return NULL;
85 }
86
87 spin_lock(&osb->osb_lock);
88 if (osb->local_system_inodes) {
89 /* Someone has initialized it for us. */
90 free = local_system_inodes;
91 local_system_inodes = osb->local_system_inodes;
92 } else
93 osb->local_system_inodes = local_system_inodes;
94 spin_unlock(&osb->osb_lock);
95 if (unlikely(free))
96 kfree(free);
97 }
98
99 index = (slot * NUM_LOCAL_SYSTEM_INODES) +
100 (type - OCFS2_FIRST_LOCAL_SYSTEM_INODE);
101
102 return &local_system_inodes[index];
67} 103}
68 104
69struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb, 105struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
@@ -74,8 +110,10 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
74 struct inode **arr = NULL; 110 struct inode **arr = NULL;
75 111
76 /* avoid the lookup if cached in local system file array */ 112 /* avoid the lookup if cached in local system file array */
77 if (is_in_system_inode_array(osb, type, slot)) 113 if (is_global_system_inode(type)) {
78 arr = &(osb->system_inodes[type]); 114 arr = &(osb->global_system_inodes[type]);
115 } else
116 arr = get_local_system_inode(osb, type, slot);
79 117
80 if (arr && ((inode = *arr) != NULL)) { 118 if (arr && ((inode = *arr) != NULL)) {
81 /* get a ref in addition to the array ref */ 119 /* get a ref in addition to the array ref */