linux/fs/ocfs2/sysfile.c
<<
>>
Prefs
   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
 168