sysfile.c (4087B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * sysfile.c 4 * 5 * Initialize, read, write, etc. system files. 6 * 7 * Copyright (C) 2002, 2004 Oracle. All rights reserved. 8 */ 9 10#include <linux/fs.h> 11#include <linux/types.h> 12#include <linux/highmem.h> 13 14#include <cluster/masklog.h> 15 16#include "ocfs2.h" 17 18#include "alloc.h" 19#include "dir.h" 20#include "inode.h" 21#include "journal.h" 22#include "sysfile.h" 23 24#include "buffer_head_io.h" 25 26static struct inode * _ocfs2_get_system_file_inode(struct ocfs2_super *osb, 27 int type, 28 u32 slot); 29 30#ifdef CONFIG_DEBUG_LOCK_ALLOC 31static struct lock_class_key ocfs2_sysfile_cluster_lock_key[NUM_SYSTEM_INODES]; 32#endif 33 34static inline int is_global_system_inode(int type) 35{ 36 return type >= OCFS2_FIRST_ONLINE_SYSTEM_INODE && 37 type <= OCFS2_LAST_GLOBAL_SYSTEM_INODE; 38} 39 40static struct inode **get_local_system_inode(struct ocfs2_super *osb, 41 int type, 42 u32 slot) 43{ 44 int index; 45 struct inode **local_system_inodes, **free = NULL; 46 47 BUG_ON(slot == OCFS2_INVALID_SLOT); 48 BUG_ON(type < OCFS2_FIRST_LOCAL_SYSTEM_INODE || 49 type > OCFS2_LAST_LOCAL_SYSTEM_INODE); 50 51 spin_lock(&osb->osb_lock); 52 local_system_inodes = osb->local_system_inodes; 53 spin_unlock(&osb->osb_lock); 54 55 if (unlikely(!local_system_inodes)) { 56 local_system_inodes = 57 kzalloc(array3_size(sizeof(struct inode *), 58 NUM_LOCAL_SYSTEM_INODES, 59 osb->max_slots), 60 GFP_NOFS); 61 if (!local_system_inodes) { 62 mlog_errno(-ENOMEM); 63 /* 64 * return NULL here so that ocfs2_get_sytem_file_inodes 65 * will try to create an inode and use it. We will try 66 * to initialize local_system_inodes next time. 67 */ 68 return NULL; 69 } 70 71 spin_lock(&osb->osb_lock); 72 if (osb->local_system_inodes) { 73 /* Someone has initialized it for us. */ 74 free = local_system_inodes; 75 local_system_inodes = osb->local_system_inodes; 76 } else 77 osb->local_system_inodes = local_system_inodes; 78 spin_unlock(&osb->osb_lock); 79 kfree(free); 80 } 81 82 index = (slot * NUM_LOCAL_SYSTEM_INODES) + 83 (type - OCFS2_FIRST_LOCAL_SYSTEM_INODE); 84 85 return &local_system_inodes[index]; 86} 87 88struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb, 89 int type, 90 u32 slot) 91{ 92 struct inode *inode = NULL; 93 struct inode **arr = NULL; 94 95 /* avoid the lookup if cached in local system file array */ 96 if (is_global_system_inode(type)) { 97 arr = &(osb->global_system_inodes[type]); 98 } else 99 arr = get_local_system_inode(osb, type, slot); 100 101 mutex_lock(&osb->system_file_mutex); 102 if (arr && ((inode = *arr) != NULL)) { 103 /* get a ref in addition to the array ref */ 104 inode = igrab(inode); 105 mutex_unlock(&osb->system_file_mutex); 106 BUG_ON(!inode); 107 108 return inode; 109 } 110 111 /* this gets one ref thru iget */ 112 inode = _ocfs2_get_system_file_inode(osb, type, slot); 113 114 /* add one more if putting into array for first time */ 115 if (arr && inode) { 116 *arr = igrab(inode); 117 BUG_ON(!*arr); 118 } 119 mutex_unlock(&osb->system_file_mutex); 120 return inode; 121} 122 123static struct inode * _ocfs2_get_system_file_inode(struct ocfs2_super *osb, 124 int type, 125 u32 slot) 126{ 127 char namebuf[40]; 128 struct inode *inode = NULL; 129 u64 blkno; 130 int status = 0; 131 132 ocfs2_sprintf_system_inode_name(namebuf, 133 sizeof(namebuf), 134 type, slot); 135 136 status = ocfs2_lookup_ino_from_name(osb->sys_root_inode, namebuf, 137 strlen(namebuf), &blkno); 138 if (status < 0) { 139 goto bail; 140 } 141 142 inode = ocfs2_iget(osb, blkno, OCFS2_FI_FLAG_SYSFILE, type); 143 if (IS_ERR(inode)) { 144 mlog_errno(PTR_ERR(inode)); 145 inode = NULL; 146 goto bail; 147 } 148#ifdef CONFIG_DEBUG_LOCK_ALLOC 149 if (type == LOCAL_USER_QUOTA_SYSTEM_INODE || 150 type == LOCAL_GROUP_QUOTA_SYSTEM_INODE || 151 type == JOURNAL_SYSTEM_INODE) { 152 /* Ignore inode lock on these inodes as the lock does not 153 * really belong to any process and lockdep cannot handle 154 * that */ 155 OCFS2_I(inode)->ip_inode_lockres.l_lockdep_map.key = NULL; 156 } else { 157 lockdep_init_map(&OCFS2_I(inode)->ip_inode_lockres. 158 l_lockdep_map, 159 ocfs2_system_inodes[type].si_name, 160 &ocfs2_sysfile_cluster_lock_key[type], 0); 161 } 162#endif 163bail: 164 165 return inode; 166} 167