Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/fs/ocfs2/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 11 kB image not shown  

Quelle  slot_map.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * slot_map.c
 *
 * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
 */


#include <linux/types.h>
#include <linux/slab.h>
#include <linux/highmem.h>

#include <cluster/masklog.h>

#include "ocfs2.h"

#include "dlmglue.h"
#include "extent_map.h"
#include "heartbeat.h"
#include "inode.h"
#include "slot_map.h"
#include "super.h"
#include "sysfile.h"
#include "ocfs2_trace.h"

#include "buffer_head_io.h"


struct ocfs2_slot {
 int sl_valid;
 unsigned int sl_node_num;
};

struct ocfs2_slot_info {
 int si_extended;
 int si_slots_per_block;
 struct inode *si_inode;
 unsigned int si_blocks;
 struct buffer_head **si_bh;
 unsigned int si_num_slots;
 struct ocfs2_slot si_slots[] __counted_by(si_num_slots);
};


static int __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
        unsigned int node_num);

static void ocfs2_invalidate_slot(struct ocfs2_slot_info *si,
      int slot_num)
{
 BUG_ON((slot_num < 0) || (slot_num >= si->si_num_slots));
 si->si_slots[slot_num].sl_valid = 0;
}

static void ocfs2_set_slot(struct ocfs2_slot_info *si,
      int slot_num, unsigned int node_num)
{
 BUG_ON((slot_num < 0) || (slot_num >= si->si_num_slots));

 si->si_slots[slot_num].sl_valid = 1;
 si->si_slots[slot_num].sl_node_num = node_num;
}

/* This version is for the extended slot map */
static void ocfs2_update_slot_info_extended(struct ocfs2_slot_info *si)
{
 int b, i, slotno;
 struct ocfs2_slot_map_extended *se;

 slotno = 0;
 for (b = 0; b < si->si_blocks; b++) {
  se = (struct ocfs2_slot_map_extended *)si->si_bh[b]->b_data;
  for (i = 0;
       (i < si->si_slots_per_block) &&
       (slotno < si->si_num_slots);
       i++, slotno++) {
   if (se->se_slots[i].es_valid)
    ocfs2_set_slot(si, slotno,
            le32_to_cpu(se->se_slots[i].es_node_num));
   else
    ocfs2_invalidate_slot(si, slotno);
  }
 }
}

/*
 * Post the slot information on disk into our slot_info struct.
 * Must be protected by osb_lock.
 */

static void ocfs2_update_slot_info_old(struct ocfs2_slot_info *si)
{
 int i;
 struct ocfs2_slot_map *sm;

 sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data;

 for (i = 0; i < si->si_num_slots; i++) {
  if (le16_to_cpu(sm->sm_slots[i]) == (u16)OCFS2_INVALID_SLOT)
   ocfs2_invalidate_slot(si, i);
  else
   ocfs2_set_slot(si, i, le16_to_cpu(sm->sm_slots[i]));
 }
}

static void ocfs2_update_slot_info(struct ocfs2_slot_info *si)
{
 /*
 * The slot data will have been refreshed when ocfs2_super_lock
 * was taken.
 */

 if (si->si_extended)
  ocfs2_update_slot_info_extended(si);
 else
  ocfs2_update_slot_info_old(si);
}

int ocfs2_refresh_slot_info(struct ocfs2_super *osb)
{
 int ret;
 struct ocfs2_slot_info *si = osb->slot_info;

 if (si == NULL)
  return 0;

 BUG_ON(si->si_blocks == 0);
 BUG_ON(si->si_bh == NULL);

 trace_ocfs2_refresh_slot_info(si->si_blocks);

 /*
 * We pass -1 as blocknr because we expect all of si->si_bh to
 * be !NULL.  Thus, ocfs2_read_blocks() will ignore blocknr.  If
 * this is not true, the read of -1 (UINT64_MAX) will fail.
 */

 ret = ocfs2_read_blocks(INODE_CACHE(si->si_inode), -1, si->si_blocks,
    si->si_bh, OCFS2_BH_IGNORE_CACHE, NULL);
 if (ret == 0) {
  spin_lock(&osb->osb_lock);
  ocfs2_update_slot_info(si);
  spin_unlock(&osb->osb_lock);
 }

 return ret;
}

/* post the our slot info stuff into it's destination bh and write it
 * out. */

static void ocfs2_update_disk_slot_extended(struct ocfs2_slot_info *si,
         int slot_num,
         struct buffer_head **bh)
{
 int blkind = slot_num / si->si_slots_per_block;
 int slotno = slot_num % si->si_slots_per_block;
 struct ocfs2_slot_map_extended *se;

 BUG_ON(blkind >= si->si_blocks);

 se = (struct ocfs2_slot_map_extended *)si->si_bh[blkind]->b_data;
 se->se_slots[slotno].es_valid = si->si_slots[slot_num].sl_valid;
 if (si->si_slots[slot_num].sl_valid)
  se->se_slots[slotno].es_node_num =
   cpu_to_le32(si->si_slots[slot_num].sl_node_num);
 *bh = si->si_bh[blkind];
}

static void ocfs2_update_disk_slot_old(struct ocfs2_slot_info *si,
           int slot_num,
           struct buffer_head **bh)
{
 int i;
 struct ocfs2_slot_map *sm;

 sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data;
 for (i = 0; i < si->si_num_slots; i++) {
  if (si->si_slots[i].sl_valid)
   sm->sm_slots[i] =
    cpu_to_le16(si->si_slots[i].sl_node_num);
  else
   sm->sm_slots[i] = cpu_to_le16(OCFS2_INVALID_SLOT);
 }
 *bh = si->si_bh[0];
}

static int ocfs2_update_disk_slot(struct ocfs2_super *osb,
      struct ocfs2_slot_info *si,
      int slot_num)
{
 int status;
 struct buffer_head *bh;

 spin_lock(&osb->osb_lock);
 if (si->si_extended)
  ocfs2_update_disk_slot_extended(si, slot_num, &bh);
 else
  ocfs2_update_disk_slot_old(si, slot_num, &bh);
 spin_unlock(&osb->osb_lock);

 status = ocfs2_write_block(osb, bh, INODE_CACHE(si->si_inode));
 if (status < 0)
  mlog_errno(status);

 return status;
}

/*
 * Calculate how many bytes are needed by the slot map.  Returns
 * an error if the slot map file is too small.
 */

static int ocfs2_slot_map_physical_size(struct ocfs2_super *osb,
     struct inode *inode,
     unsigned long long *bytes)
{
 unsigned long long bytes_needed;

 if (ocfs2_uses_extended_slot_map(osb)) {
  bytes_needed = osb->max_slots *
   sizeof(struct ocfs2_extended_slot);
 } else {
  bytes_needed = osb->max_slots * sizeof(__le16);
 }
 if (bytes_needed > i_size_read(inode)) {
  mlog(ML_ERROR,
       "Slot map file is too small! (size %llu, needed %llu)\n",
       i_size_read(inode), bytes_needed);
  return -ENOSPC;
 }

 *bytes = bytes_needed;
 return 0;
}

/* try to find global node in the slot info. Returns -ENOENT
 * if nothing is found. */

static int __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
        unsigned int node_num)
{
 int i, ret = -ENOENT;

 for(i = 0; i < si->si_num_slots; i++) {
  if (si->si_slots[i].sl_valid &&
      (node_num == si->si_slots[i].sl_node_num)) {
   ret = i;
   break;
  }
 }

 return ret;
}

static int __ocfs2_find_empty_slot(struct ocfs2_slot_info *si,
       int preferred)
{
 int i, ret = -ENOSPC;

 if ((preferred >= 0) && (preferred < si->si_num_slots)) {
  if (!si->si_slots[preferred].sl_valid) {
   ret = preferred;
   goto out;
  }
 }

 for(i = 0; i < si->si_num_slots; i++) {
  if (!si->si_slots[i].sl_valid) {
   ret = i;
   break;
  }
 }
out:
 return ret;
}

int ocfs2_node_num_to_slot(struct ocfs2_super *osb, unsigned int node_num)
{
 int slot;
 struct ocfs2_slot_info *si = osb->slot_info;

 spin_lock(&osb->osb_lock);
 slot = __ocfs2_node_num_to_slot(si, node_num);
 spin_unlock(&osb->osb_lock);

 return slot;
}

int ocfs2_slot_to_node_num_locked(struct ocfs2_super *osb, int slot_num,
      unsigned int *node_num)
{
 struct ocfs2_slot_info *si = osb->slot_info;

 assert_spin_locked(&osb->osb_lock);

 BUG_ON(slot_num < 0);
 BUG_ON(slot_num >= osb->max_slots);

 if (!si->si_slots[slot_num].sl_valid)
  return -ENOENT;

 *node_num = si->si_slots[slot_num].sl_node_num;
 return 0;
}

static void __ocfs2_free_slot_info(struct ocfs2_slot_info *si)
{
 unsigned int i;

 if (si == NULL)
  return;

 iput(si->si_inode);
 if (si->si_bh) {
  for (i = 0; i < si->si_blocks; i++) {
   if (si->si_bh[i]) {
    brelse(si->si_bh[i]);
    si->si_bh[i] = NULL;
   }
  }
  kfree(si->si_bh);
 }

 kfree(si);
}

int ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num)
{
 struct ocfs2_slot_info *si = osb->slot_info;

 if (si == NULL)
  return 0;

 spin_lock(&osb->osb_lock);
 ocfs2_invalidate_slot(si, slot_num);
 spin_unlock(&osb->osb_lock);

 return ocfs2_update_disk_slot(osb, osb->slot_info, slot_num);
}

static int ocfs2_map_slot_buffers(struct ocfs2_super *osb,
      struct ocfs2_slot_info *si)
{
 int status = 0;
 u64 blkno;
 unsigned long long blocks, bytes = 0;
 unsigned int i;
 struct buffer_head *bh;

 status = ocfs2_slot_map_physical_size(osb, si->si_inode, &bytes);
 if (status)
  goto bail;

 blocks = ocfs2_blocks_for_bytes(si->si_inode->i_sb, bytes);
 BUG_ON(blocks > UINT_MAX);
 si->si_blocks = blocks;
 if (!si->si_blocks)
  goto bail;

 if (si->si_extended)
  si->si_slots_per_block =
   (osb->sb->s_blocksize /
    sizeof(struct ocfs2_extended_slot));
 else
  si->si_slots_per_block = osb->sb->s_blocksize / sizeof(__le16);

 /* The size checks above should ensure this */
 BUG_ON((osb->max_slots / si->si_slots_per_block) > blocks);

 trace_ocfs2_map_slot_buffers(bytes, si->si_blocks);

 si->si_bh = kcalloc(si->si_blocks, sizeof(struct buffer_head *),
       GFP_KERNEL);
 if (!si->si_bh) {
  status = -ENOMEM;
  mlog_errno(status);
  goto bail;
 }

 for (i = 0; i < si->si_blocks; i++) {
  status = ocfs2_extent_map_get_blocks(si->si_inode, i,
           &blkno, NULL, NULL);
  if (status < 0) {
   mlog_errno(status);
   goto bail;
  }

  trace_ocfs2_map_slot_buffers_block((unsigned long long)blkno, i);

  bh = NULL;  /* Acquire a fresh bh */
  status = ocfs2_read_blocks(INODE_CACHE(si->si_inode), blkno,
        1, &bh, OCFS2_BH_IGNORE_CACHE, NULL);
  if (status < 0) {
   mlog_errno(status);
   goto bail;
  }

  si->si_bh[i] = bh;
 }

bail:
 return status;
}

int ocfs2_init_slot_info(struct ocfs2_super *osb)
{
 int status;
 struct inode *inode = NULL;
 struct ocfs2_slot_info *si;

 si = kzalloc(struct_size(si, si_slots, osb->max_slots), GFP_KERNEL);
 if (!si) {
  status = -ENOMEM;
  mlog_errno(status);
  return status;
 }

 si->si_extended = ocfs2_uses_extended_slot_map(osb);
 si->si_num_slots = osb->max_slots;

 inode = ocfs2_get_system_file_inode(osb, SLOT_MAP_SYSTEM_INODE,
         OCFS2_INVALID_SLOT);
 if (!inode) {
  status = -EINVAL;
  mlog_errno(status);
  goto bail;
 }

 si->si_inode = inode;
 status = ocfs2_map_slot_buffers(osb, si);
 if (status < 0) {
  mlog_errno(status);
  goto bail;
 }

 osb->slot_info = (struct ocfs2_slot_info *)si;
bail:
 if (status < 0)
  __ocfs2_free_slot_info(si);

 return status;
}

void ocfs2_free_slot_info(struct ocfs2_super *osb)
{
 struct ocfs2_slot_info *si = osb->slot_info;

 osb->slot_info = NULL;
 __ocfs2_free_slot_info(si);
}

int ocfs2_find_slot(struct ocfs2_super *osb)
{
 int status;
 int slot;
 struct ocfs2_slot_info *si;

 si = osb->slot_info;

 spin_lock(&osb->osb_lock);
 ocfs2_update_slot_info(si);

 /* search for ourselves first and take the slot if it already
 * exists. Perhaps we need to mark this in a variable for our
 * own journal recovery? Possibly not, though we certainly
 * need to warn to the user */

 slot = __ocfs2_node_num_to_slot(si, osb->node_num);
 if (slot < 0) {
  /* if no slot yet, then just take 1st available
 * one. */

  slot = __ocfs2_find_empty_slot(si, osb->preferred_slot);
  if (slot < 0) {
   spin_unlock(&osb->osb_lock);
   mlog(ML_ERROR, "no free slots available!\n");
   status = -EINVAL;
   goto bail;
  }
 } else
  printk(KERN_INFO "ocfs2: Slot %d on device (%s) was already "
         "allocated to this node!\n", slot, osb->dev_str);

 ocfs2_set_slot(si, slot, osb->node_num);
 osb->slot_num = slot;
 spin_unlock(&osb->osb_lock);

 trace_ocfs2_find_slot(osb->slot_num);

 status = ocfs2_update_disk_slot(osb, si, osb->slot_num);
 if (status < 0) {
  mlog_errno(status);
  /*
 * if write block failed, invalidate slot to avoid overwrite
 * slot during dismount in case another node rightly has mounted
 */

  spin_lock(&osb->osb_lock);
  ocfs2_invalidate_slot(si, osb->slot_num);
  osb->slot_num = OCFS2_INVALID_SLOT;
  spin_unlock(&osb->osb_lock);
 }

bail:
 return status;
}

void ocfs2_put_slot(struct ocfs2_super *osb)
{
 int status, slot_num;
 struct ocfs2_slot_info *si = osb->slot_info;

 if (!si)
  return;

 spin_lock(&osb->osb_lock);
 ocfs2_update_slot_info(si);

 slot_num = osb->slot_num;
 ocfs2_invalidate_slot(si, osb->slot_num);
 osb->slot_num = OCFS2_INVALID_SLOT;
 spin_unlock(&osb->osb_lock);

 status = ocfs2_update_disk_slot(osb, si, slot_num);
 if (status < 0)
  mlog_errno(status);

 ocfs2_free_slot_info(osb);
}

Messung V0.5
C=97 H=86 G=91

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.