Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * sysfile.c
0004  *
0005  * Initialize, read, write, etc. system files.
0006  *
0007  * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
0008  */
0009 
0010 #include <linux/fs.h>
0011 #include <linux/types.h>
0012 #include <linux/highmem.h>
0013 
0014 #include <cluster/masklog.h>
0015 
0016 #include "ocfs2.h"
0017 
0018 #include "alloc.h"
0019 #include "dir.h"
0020 #include "inode.h"
0021 #include "journal.h"
0022 #include "sysfile.h"
0023 
0024 #include "buffer_head_io.h"
0025 
0026 static struct inode * _ocfs2_get_system_file_inode(struct ocfs2_super *osb,
0027                            int type,
0028                            u32 slot);
0029 
0030 #ifdef CONFIG_DEBUG_LOCK_ALLOC
0031 static struct lock_class_key ocfs2_sysfile_cluster_lock_key[NUM_SYSTEM_INODES];
0032 #endif
0033 
0034 static inline int is_global_system_inode(int type)
0035 {
0036     return type >= OCFS2_FIRST_ONLINE_SYSTEM_INODE &&
0037         type <= OCFS2_LAST_GLOBAL_SYSTEM_INODE;
0038 }
0039 
0040 static struct inode **get_local_system_inode(struct ocfs2_super *osb,
0041                          int type,
0042                          u32 slot)
0043 {
0044     int index;
0045     struct inode **local_system_inodes, **free = NULL;
0046 
0047     BUG_ON(slot == OCFS2_INVALID_SLOT);
0048     BUG_ON(type < OCFS2_FIRST_LOCAL_SYSTEM_INODE ||
0049            type > OCFS2_LAST_LOCAL_SYSTEM_INODE);
0050 
0051     spin_lock(&osb->osb_lock);
0052     local_system_inodes = osb->local_system_inodes;
0053     spin_unlock(&osb->osb_lock);
0054 
0055     if (unlikely(!local_system_inodes)) {
0056         local_system_inodes =
0057             kzalloc(array3_size(sizeof(struct inode *),
0058                         NUM_LOCAL_SYSTEM_INODES,
0059                         osb->max_slots),
0060                 GFP_NOFS);
0061         if (!local_system_inodes) {
0062             mlog_errno(-ENOMEM);
0063             /*
0064              * return NULL here so that ocfs2_get_sytem_file_inodes
0065              * will try to create an inode and use it. We will try
0066              * to initialize local_system_inodes next time.
0067              */
0068             return NULL;
0069         }
0070 
0071         spin_lock(&osb->osb_lock);
0072         if (osb->local_system_inodes) {
0073             /* Someone has initialized it for us. */
0074             free = local_system_inodes;
0075             local_system_inodes = osb->local_system_inodes;
0076         } else
0077             osb->local_system_inodes = local_system_inodes;
0078         spin_unlock(&osb->osb_lock);
0079         kfree(free);
0080     }
0081 
0082     index = (slot * NUM_LOCAL_SYSTEM_INODES) +
0083         (type - OCFS2_FIRST_LOCAL_SYSTEM_INODE);
0084 
0085     return &local_system_inodes[index];
0086 }
0087 
0088 struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
0089                       int type,
0090                       u32 slot)
0091 {
0092     struct inode *inode = NULL;
0093     struct inode **arr = NULL;
0094 
0095     /* avoid the lookup if cached in local system file array */
0096     if (is_global_system_inode(type)) {
0097         arr = &(osb->global_system_inodes[type]);
0098     } else
0099         arr = get_local_system_inode(osb, type, slot);
0100 
0101     mutex_lock(&osb->system_file_mutex);
0102     if (arr && ((inode = *arr) != NULL)) {
0103         /* get a ref in addition to the array ref */
0104         inode = igrab(inode);
0105         mutex_unlock(&osb->system_file_mutex);
0106         BUG_ON(!inode);
0107 
0108         return inode;
0109     }
0110 
0111     /* this gets one ref thru iget */
0112     inode = _ocfs2_get_system_file_inode(osb, type, slot);
0113 
0114     /* add one more if putting into array for first time */
0115     if (arr && inode) {
0116         *arr = igrab(inode);
0117         BUG_ON(!*arr);
0118     }
0119     mutex_unlock(&osb->system_file_mutex);
0120     return inode;
0121 }
0122 
0123 static struct inode * _ocfs2_get_system_file_inode(struct ocfs2_super *osb,
0124                            int type,
0125                            u32 slot)
0126 {
0127     char namebuf[40];
0128     struct inode *inode = NULL;
0129     u64 blkno;
0130     int status = 0;
0131 
0132     ocfs2_sprintf_system_inode_name(namebuf,
0133                     sizeof(namebuf),
0134                     type, slot);
0135 
0136     status = ocfs2_lookup_ino_from_name(osb->sys_root_inode, namebuf,
0137                         strlen(namebuf), &blkno);
0138     if (status < 0) {
0139         goto bail;
0140     }
0141 
0142     inode = ocfs2_iget(osb, blkno, OCFS2_FI_FLAG_SYSFILE, type);
0143     if (IS_ERR(inode)) {
0144         mlog_errno(PTR_ERR(inode));
0145         inode = NULL;
0146         goto bail;
0147     }
0148 #ifdef CONFIG_DEBUG_LOCK_ALLOC
0149     if (type == LOCAL_USER_QUOTA_SYSTEM_INODE ||
0150         type == LOCAL_GROUP_QUOTA_SYSTEM_INODE ||
0151         type == JOURNAL_SYSTEM_INODE) {
0152         /* Ignore inode lock on these inodes as the lock does not
0153          * really belong to any process and lockdep cannot handle
0154          * that */
0155         OCFS2_I(inode)->ip_inode_lockres.l_lockdep_map.key = NULL;
0156     } else {
0157         lockdep_init_map(&OCFS2_I(inode)->ip_inode_lockres.
0158                                 l_lockdep_map,
0159                  ocfs2_system_inodes[type].si_name,
0160                  &ocfs2_sysfile_cluster_lock_key[type], 0);
0161     }
0162 #endif
0163 bail:
0164 
0165     return inode;
0166 }
0167