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  
26  static struct inode * _ocfs2_get_system_file_inode(struct ocfs2_super *osb,
27  						   int type,
28  						   u32 slot);
29  
30  #ifdef CONFIG_DEBUG_LOCK_ALLOC
31  static struct lock_class_key ocfs2_sysfile_cluster_lock_key[NUM_SYSTEM_INODES];
32  #endif
33  
is_global_system_inode(int type)34  static 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  
get_local_system_inode(struct ocfs2_super * osb,int type,u32 slot)40  static 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  
ocfs2_get_system_file_inode(struct ocfs2_super * osb,int type,u32 slot)88  struct 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  
_ocfs2_get_system_file_inode(struct ocfs2_super * osb,int type,u32 slot)123  static 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
163  bail:
164  
165  	return inode;
166  }
167  
168