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