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                if (unlikely(free))
  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        if (arr && ((inode = *arr) != NULL)) {
 118                /* get a ref in addition to the array ref */
 119                inode = igrab(inode);
 120                BUG_ON(!inode);
 121
 122                return inode;
 123        }
 124
 125        /* this gets one ref thru iget */
 126        inode = _ocfs2_get_system_file_inode(osb, type, slot);
 127
 128        /* add one more if putting into array for first time */
 129        if (arr && inode) {
 130                *arr = igrab(inode);
 131                BUG_ON(!*arr);
 132        }
 133        return inode;
 134}
 135
 136static struct inode * _ocfs2_get_system_file_inode(struct ocfs2_super *osb,
 137                                                   int type,
 138                                                   u32 slot)
 139{
 140        char namebuf[40];
 141        struct inode *inode = NULL;
 142        u64 blkno;
 143        int status = 0;
 144
 145        ocfs2_sprintf_system_inode_name(namebuf,
 146                                        sizeof(namebuf),
 147                                        type, slot);
 148
 149        status = ocfs2_lookup_ino_from_name(osb->sys_root_inode, namebuf,
 150                                            strlen(namebuf), &blkno);
 151        if (status < 0) {
 152                goto bail;
 153        }
 154
 155        inode = ocfs2_iget(osb, blkno, OCFS2_FI_FLAG_SYSFILE, type);
 156        if (IS_ERR(inode)) {
 157                mlog_errno(PTR_ERR(inode));
 158                inode = NULL;
 159                goto bail;
 160        }
 161#ifdef CONFIG_DEBUG_LOCK_ALLOC
 162        if (type == LOCAL_USER_QUOTA_SYSTEM_INODE ||
 163            type == LOCAL_GROUP_QUOTA_SYSTEM_INODE ||
 164            type == JOURNAL_SYSTEM_INODE) {
 165                /* Ignore inode lock on these inodes as the lock does not
 166                 * really belong to any process and lockdep cannot handle
 167                 * that */
 168                OCFS2_I(inode)->ip_inode_lockres.l_lockdep_map.key = NULL;
 169        } else {
 170                lockdep_init_map(&OCFS2_I(inode)->ip_inode_lockres.
 171                                                                l_lockdep_map,
 172                                 ocfs2_system_inodes[type].si_name,
 173                                 &ocfs2_sysfile_cluster_lock_key[type], 0);
 174        }
 175#endif
 176bail:
 177
 178        return inode;
 179}
 180
 181
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.