diff options
Diffstat (limited to 'fs/ocfs2/sysfile.c')
| -rw-r--r-- | fs/ocfs2/sysfile.c | 60 |
1 files changed, 49 insertions, 11 deletions
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 | ||
| 47 | static inline int is_global_system_inode(int type); | ||
| 48 | static 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 |
| 53 | static struct lock_class_key ocfs2_sysfile_cluster_lock_key[NUM_SYSTEM_INODES]; | 48 | static 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 | ||
| 62 | static inline int is_in_system_inode_array(struct ocfs2_super *osb, | 57 | static 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 | ||
| 69 | struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb, | 105 | 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, | |||
| 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 */ |
