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