Merge tag 's390-5.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
[linux-2.6-microblaze.git] / fs / ocfs2 / sysfile.c
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
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
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
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
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