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 = kzalloc(sizeof(struct inode *) *
  73                                              NUM_LOCAL_SYSTEM_INODES *
  74                                              osb->max_slots,
  75                                              GFP_NOFS);
  76                if (!local_system_inodes) {
  77                        mlog_errno(-ENOMEM);
  78                        /*
  79                         * return NULL here so that ocfs2_get_sytem_file_inodes
  80                         * will try to create an inode and use it. We will try
  81                         * to initialize local_system_inodes next time.
  82                         */
  83                        return NULL;
  84                }
  85
  86                spin_lock(&osb->osb_lock);
  87                if (osb->local_system_inodes) {
  88                        /* Someone has initialized it for us. */
  89                        free = local_system_inodes;
  90                        local_system_inodes = osb->local_system_inodes;
  91                } else
  92                        osb->local_system_inodes = local_system_inodes;
  93                spin_unlock(&osb->osb_lock);
  94                kfree(free);
  95        }
  96
  97        index = (slot * NUM_LOCAL_SYSTEM_INODES) +
  98                (type - OCFS2_FIRST_LOCAL_SYSTEM_INODE);
  99
 100        return &local_system_inodes[index];
 101}
 102
 103struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
 104                                          int type,
 105                                          u32 slot)
 106{
 107        struct inode *inode = NULL;
 108        struct inode **arr = NULL;
 109
 110        /* avoid the lookup if cached in local system file array */
 111        if (is_global_system_inode(type)) {
 112                arr = &(osb->global_system_inodes[type]);
 113        } else
 114                arr = get_local_system_inode(osb, type, slot);
 115
 116        mutex_lock(&osb->system_file_mutex);
 117        if (arr && ((inode = *arr) != NULL)) {
 118                /* get a ref in addition to the array ref */
 119                inode = igrab(inode);
 120                mutex_unlock(&osb->system_file_mutex);
 121                BUG_ON(!inode);
 122
 123                return inode;
 124        }
 125
 126        /* this gets one ref thru iget */
 127        inode = _ocfs2_get_system_file_inode(osb, type, slot);
 128
 129        /* add one more if putting into array for first time */
 130        if (arr && inode) {
 131                *arr = igrab(inode);
 132                BUG_ON(!*arr);
 133        }
 134        mutex_unlock(&osb->system_file_mutex);
 135        return inode;
 136}
 137
 138static struct inode * _ocfs2_get_system_file_inode(struct ocfs2_super *osb,
 139                                                   int type,
 140                                                   u32 slot)
 141{
 142        char namebuf[40];
 143        struct inode *inode = NULL;
 144        u64 blkno;
 145        int status = 0;
 146
 147        ocfs2_sprintf_system_inode_name(namebuf,
 148                                        sizeof(namebuf),
 149                                        type, slot);
 150
 151        status = ocfs2_lookup_ino_from_name(osb->sys_root_inode, namebuf,
 152                                            strlen(namebuf), &blkno);
 153        if (status < 0) {
 154                goto bail;
 155        }
 156
 157        inode = ocfs2_iget(osb, blkno, OCFS2_FI_FLAG_SYSFILE, type);
 158        if (IS_ERR(inode)) {
 159                mlog_errno(PTR_ERR(inode));
 160                inode = NULL;
 161                goto bail;
 162        }
 163#ifdef CONFIG_DEBUG_LOCK_ALLOC
 164        if (type == LOCAL_USER_QUOTA_SYSTEM_INODE ||
 165            type == LOCAL_GROUP_QUOTA_SYSTEM_INODE ||
 166            type == JOURNAL_SYSTEM_INODE) {
 167                /* Ignore inode lock on these inodes as the lock does not
 168                 * really belong to any process and lockdep cannot handle
 169                 * that */
 170                OCFS2_I(inode)->ip_inode_lockres.l_lockdep_map.key = NULL;
 171        } else {
 172                lockdep_init_map(&OCFS2_I(inode)->ip_inode_lockres.
 173                                                                l_lockdep_map,
 174                                 ocfs2_system_inodes[type].si_name,
 175                                 &ocfs2_sysfile_cluster_lock_key[type], 0);
 176        }
 177#endif
 178bail:
 179
 180        return inode;
 181}
 182
 183