|
@@ -44,11 +44,6 @@ static struct inode * _ocfs2_get_system_file_inode(struct ocfs2_super *osb,
|
|
|
int type,
|
|
|
u32 slot);
|
|
|
|
|
|
-static inline int is_global_system_inode(int type);
|
|
|
-static inline int is_in_system_inode_array(struct ocfs2_super *osb,
|
|
|
- int type,
|
|
|
- u32 slot);
|
|
|
-
|
|
|
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
|
|
static struct lock_class_key ocfs2_sysfile_cluster_lock_key[NUM_SYSTEM_INODES];
|
|
|
#endif
|
|
@@ -59,11 +54,52 @@ static inline int is_global_system_inode(int type)
|
|
|
type <= OCFS2_LAST_GLOBAL_SYSTEM_INODE;
|
|
|
}
|
|
|
|
|
|
-static inline int is_in_system_inode_array(struct ocfs2_super *osb,
|
|
|
- int type,
|
|
|
- u32 slot)
|
|
|
+static struct inode **get_local_system_inode(struct ocfs2_super *osb,
|
|
|
+ int type,
|
|
|
+ u32 slot)
|
|
|
{
|
|
|
- return slot == osb->slot_num || is_global_system_inode(type);
|
|
|
+ int index;
|
|
|
+ struct inode **local_system_inodes, **free = NULL;
|
|
|
+
|
|
|
+ BUG_ON(slot == OCFS2_INVALID_SLOT);
|
|
|
+ BUG_ON(type < OCFS2_FIRST_LOCAL_SYSTEM_INODE ||
|
|
|
+ type > OCFS2_LAST_LOCAL_SYSTEM_INODE);
|
|
|
+
|
|
|
+ spin_lock(&osb->osb_lock);
|
|
|
+ local_system_inodes = osb->local_system_inodes;
|
|
|
+ spin_unlock(&osb->osb_lock);
|
|
|
+
|
|
|
+ if (unlikely(!local_system_inodes)) {
|
|
|
+ local_system_inodes = kzalloc(sizeof(struct inode *) *
|
|
|
+ NUM_LOCAL_SYSTEM_INODES *
|
|
|
+ osb->max_slots,
|
|
|
+ GFP_NOFS);
|
|
|
+ if (!local_system_inodes) {
|
|
|
+ mlog_errno(-ENOMEM);
|
|
|
+ /*
|
|
|
+ * return NULL here so that ocfs2_get_sytem_file_inodes
|
|
|
+ * will try to create an inode and use it. We will try
|
|
|
+ * to initialize local_system_inodes next time.
|
|
|
+ */
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ spin_lock(&osb->osb_lock);
|
|
|
+ if (osb->local_system_inodes) {
|
|
|
+ /* Someone has initialized it for us. */
|
|
|
+ free = local_system_inodes;
|
|
|
+ local_system_inodes = osb->local_system_inodes;
|
|
|
+ } else
|
|
|
+ osb->local_system_inodes = local_system_inodes;
|
|
|
+ spin_unlock(&osb->osb_lock);
|
|
|
+ if (unlikely(free))
|
|
|
+ kfree(free);
|
|
|
+ }
|
|
|
+
|
|
|
+ index = (slot * NUM_LOCAL_SYSTEM_INODES) +
|
|
|
+ (type - OCFS2_FIRST_LOCAL_SYSTEM_INODE);
|
|
|
+
|
|
|
+ return &local_system_inodes[index];
|
|
|
}
|
|
|
|
|
|
struct 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,
|
|
|
struct inode **arr = NULL;
|
|
|
|
|
|
/* avoid the lookup if cached in local system file array */
|
|
|
- if (is_in_system_inode_array(osb, type, slot))
|
|
|
- arr = &(osb->system_inodes[type]);
|
|
|
+ if (is_global_system_inode(type)) {
|
|
|
+ arr = &(osb->global_system_inodes[type]);
|
|
|
+ } else
|
|
|
+ arr = get_local_system_inode(osb, type, slot);
|
|
|
|
|
|
if (arr && ((inode = *arr) != NULL)) {
|
|
|
/* get a ref in addition to the array ref */
|