162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * slot_map.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2002, 2004 Oracle. All rights reserved. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/types.h> 962306a36Sopenharmony_ci#include <linux/slab.h> 1062306a36Sopenharmony_ci#include <linux/highmem.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <cluster/masklog.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include "ocfs2.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "dlmglue.h" 1762306a36Sopenharmony_ci#include "extent_map.h" 1862306a36Sopenharmony_ci#include "heartbeat.h" 1962306a36Sopenharmony_ci#include "inode.h" 2062306a36Sopenharmony_ci#include "slot_map.h" 2162306a36Sopenharmony_ci#include "super.h" 2262306a36Sopenharmony_ci#include "sysfile.h" 2362306a36Sopenharmony_ci#include "ocfs2_trace.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include "buffer_head_io.h" 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistruct ocfs2_slot { 2962306a36Sopenharmony_ci int sl_valid; 3062306a36Sopenharmony_ci unsigned int sl_node_num; 3162306a36Sopenharmony_ci}; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistruct ocfs2_slot_info { 3462306a36Sopenharmony_ci int si_extended; 3562306a36Sopenharmony_ci int si_slots_per_block; 3662306a36Sopenharmony_ci struct inode *si_inode; 3762306a36Sopenharmony_ci unsigned int si_blocks; 3862306a36Sopenharmony_ci struct buffer_head **si_bh; 3962306a36Sopenharmony_ci unsigned int si_num_slots; 4062306a36Sopenharmony_ci struct ocfs2_slot si_slots[]; 4162306a36Sopenharmony_ci}; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic int __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si, 4562306a36Sopenharmony_ci unsigned int node_num); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistatic void ocfs2_invalidate_slot(struct ocfs2_slot_info *si, 4862306a36Sopenharmony_ci int slot_num) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci BUG_ON((slot_num < 0) || (slot_num >= si->si_num_slots)); 5162306a36Sopenharmony_ci si->si_slots[slot_num].sl_valid = 0; 5262306a36Sopenharmony_ci} 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic void ocfs2_set_slot(struct ocfs2_slot_info *si, 5562306a36Sopenharmony_ci int slot_num, unsigned int node_num) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci BUG_ON((slot_num < 0) || (slot_num >= si->si_num_slots)); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci si->si_slots[slot_num].sl_valid = 1; 6062306a36Sopenharmony_ci si->si_slots[slot_num].sl_node_num = node_num; 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/* This version is for the extended slot map */ 6462306a36Sopenharmony_cistatic void ocfs2_update_slot_info_extended(struct ocfs2_slot_info *si) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci int b, i, slotno; 6762306a36Sopenharmony_ci struct ocfs2_slot_map_extended *se; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci slotno = 0; 7062306a36Sopenharmony_ci for (b = 0; b < si->si_blocks; b++) { 7162306a36Sopenharmony_ci se = (struct ocfs2_slot_map_extended *)si->si_bh[b]->b_data; 7262306a36Sopenharmony_ci for (i = 0; 7362306a36Sopenharmony_ci (i < si->si_slots_per_block) && 7462306a36Sopenharmony_ci (slotno < si->si_num_slots); 7562306a36Sopenharmony_ci i++, slotno++) { 7662306a36Sopenharmony_ci if (se->se_slots[i].es_valid) 7762306a36Sopenharmony_ci ocfs2_set_slot(si, slotno, 7862306a36Sopenharmony_ci le32_to_cpu(se->se_slots[i].es_node_num)); 7962306a36Sopenharmony_ci else 8062306a36Sopenharmony_ci ocfs2_invalidate_slot(si, slotno); 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci/* 8662306a36Sopenharmony_ci * Post the slot information on disk into our slot_info struct. 8762306a36Sopenharmony_ci * Must be protected by osb_lock. 8862306a36Sopenharmony_ci */ 8962306a36Sopenharmony_cistatic void ocfs2_update_slot_info_old(struct ocfs2_slot_info *si) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci int i; 9262306a36Sopenharmony_ci struct ocfs2_slot_map *sm; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci for (i = 0; i < si->si_num_slots; i++) { 9762306a36Sopenharmony_ci if (le16_to_cpu(sm->sm_slots[i]) == (u16)OCFS2_INVALID_SLOT) 9862306a36Sopenharmony_ci ocfs2_invalidate_slot(si, i); 9962306a36Sopenharmony_ci else 10062306a36Sopenharmony_ci ocfs2_set_slot(si, i, le16_to_cpu(sm->sm_slots[i])); 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic void ocfs2_update_slot_info(struct ocfs2_slot_info *si) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci /* 10762306a36Sopenharmony_ci * The slot data will have been refreshed when ocfs2_super_lock 10862306a36Sopenharmony_ci * was taken. 10962306a36Sopenharmony_ci */ 11062306a36Sopenharmony_ci if (si->si_extended) 11162306a36Sopenharmony_ci ocfs2_update_slot_info_extended(si); 11262306a36Sopenharmony_ci else 11362306a36Sopenharmony_ci ocfs2_update_slot_info_old(si); 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ciint ocfs2_refresh_slot_info(struct ocfs2_super *osb) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci int ret; 11962306a36Sopenharmony_ci struct ocfs2_slot_info *si = osb->slot_info; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci if (si == NULL) 12262306a36Sopenharmony_ci return 0; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci BUG_ON(si->si_blocks == 0); 12562306a36Sopenharmony_ci BUG_ON(si->si_bh == NULL); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci trace_ocfs2_refresh_slot_info(si->si_blocks); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci /* 13062306a36Sopenharmony_ci * We pass -1 as blocknr because we expect all of si->si_bh to 13162306a36Sopenharmony_ci * be !NULL. Thus, ocfs2_read_blocks() will ignore blocknr. If 13262306a36Sopenharmony_ci * this is not true, the read of -1 (UINT64_MAX) will fail. 13362306a36Sopenharmony_ci */ 13462306a36Sopenharmony_ci ret = ocfs2_read_blocks(INODE_CACHE(si->si_inode), -1, si->si_blocks, 13562306a36Sopenharmony_ci si->si_bh, OCFS2_BH_IGNORE_CACHE, NULL); 13662306a36Sopenharmony_ci if (ret == 0) { 13762306a36Sopenharmony_ci spin_lock(&osb->osb_lock); 13862306a36Sopenharmony_ci ocfs2_update_slot_info(si); 13962306a36Sopenharmony_ci spin_unlock(&osb->osb_lock); 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci return ret; 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci/* post the our slot info stuff into it's destination bh and write it 14662306a36Sopenharmony_ci * out. */ 14762306a36Sopenharmony_cistatic void ocfs2_update_disk_slot_extended(struct ocfs2_slot_info *si, 14862306a36Sopenharmony_ci int slot_num, 14962306a36Sopenharmony_ci struct buffer_head **bh) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci int blkind = slot_num / si->si_slots_per_block; 15262306a36Sopenharmony_ci int slotno = slot_num % si->si_slots_per_block; 15362306a36Sopenharmony_ci struct ocfs2_slot_map_extended *se; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci BUG_ON(blkind >= si->si_blocks); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci se = (struct ocfs2_slot_map_extended *)si->si_bh[blkind]->b_data; 15862306a36Sopenharmony_ci se->se_slots[slotno].es_valid = si->si_slots[slot_num].sl_valid; 15962306a36Sopenharmony_ci if (si->si_slots[slot_num].sl_valid) 16062306a36Sopenharmony_ci se->se_slots[slotno].es_node_num = 16162306a36Sopenharmony_ci cpu_to_le32(si->si_slots[slot_num].sl_node_num); 16262306a36Sopenharmony_ci *bh = si->si_bh[blkind]; 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic void ocfs2_update_disk_slot_old(struct ocfs2_slot_info *si, 16662306a36Sopenharmony_ci int slot_num, 16762306a36Sopenharmony_ci struct buffer_head **bh) 16862306a36Sopenharmony_ci{ 16962306a36Sopenharmony_ci int i; 17062306a36Sopenharmony_ci struct ocfs2_slot_map *sm; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data; 17362306a36Sopenharmony_ci for (i = 0; i < si->si_num_slots; i++) { 17462306a36Sopenharmony_ci if (si->si_slots[i].sl_valid) 17562306a36Sopenharmony_ci sm->sm_slots[i] = 17662306a36Sopenharmony_ci cpu_to_le16(si->si_slots[i].sl_node_num); 17762306a36Sopenharmony_ci else 17862306a36Sopenharmony_ci sm->sm_slots[i] = cpu_to_le16(OCFS2_INVALID_SLOT); 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci *bh = si->si_bh[0]; 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic int ocfs2_update_disk_slot(struct ocfs2_super *osb, 18462306a36Sopenharmony_ci struct ocfs2_slot_info *si, 18562306a36Sopenharmony_ci int slot_num) 18662306a36Sopenharmony_ci{ 18762306a36Sopenharmony_ci int status; 18862306a36Sopenharmony_ci struct buffer_head *bh; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci spin_lock(&osb->osb_lock); 19162306a36Sopenharmony_ci if (si->si_extended) 19262306a36Sopenharmony_ci ocfs2_update_disk_slot_extended(si, slot_num, &bh); 19362306a36Sopenharmony_ci else 19462306a36Sopenharmony_ci ocfs2_update_disk_slot_old(si, slot_num, &bh); 19562306a36Sopenharmony_ci spin_unlock(&osb->osb_lock); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci status = ocfs2_write_block(osb, bh, INODE_CACHE(si->si_inode)); 19862306a36Sopenharmony_ci if (status < 0) 19962306a36Sopenharmony_ci mlog_errno(status); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci return status; 20262306a36Sopenharmony_ci} 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci/* 20562306a36Sopenharmony_ci * Calculate how many bytes are needed by the slot map. Returns 20662306a36Sopenharmony_ci * an error if the slot map file is too small. 20762306a36Sopenharmony_ci */ 20862306a36Sopenharmony_cistatic int ocfs2_slot_map_physical_size(struct ocfs2_super *osb, 20962306a36Sopenharmony_ci struct inode *inode, 21062306a36Sopenharmony_ci unsigned long long *bytes) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci unsigned long long bytes_needed; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci if (ocfs2_uses_extended_slot_map(osb)) { 21562306a36Sopenharmony_ci bytes_needed = osb->max_slots * 21662306a36Sopenharmony_ci sizeof(struct ocfs2_extended_slot); 21762306a36Sopenharmony_ci } else { 21862306a36Sopenharmony_ci bytes_needed = osb->max_slots * sizeof(__le16); 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci if (bytes_needed > i_size_read(inode)) { 22162306a36Sopenharmony_ci mlog(ML_ERROR, 22262306a36Sopenharmony_ci "Slot map file is too small! (size %llu, needed %llu)\n", 22362306a36Sopenharmony_ci i_size_read(inode), bytes_needed); 22462306a36Sopenharmony_ci return -ENOSPC; 22562306a36Sopenharmony_ci } 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci *bytes = bytes_needed; 22862306a36Sopenharmony_ci return 0; 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci/* try to find global node in the slot info. Returns -ENOENT 23262306a36Sopenharmony_ci * if nothing is found. */ 23362306a36Sopenharmony_cistatic int __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si, 23462306a36Sopenharmony_ci unsigned int node_num) 23562306a36Sopenharmony_ci{ 23662306a36Sopenharmony_ci int i, ret = -ENOENT; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci for(i = 0; i < si->si_num_slots; i++) { 23962306a36Sopenharmony_ci if (si->si_slots[i].sl_valid && 24062306a36Sopenharmony_ci (node_num == si->si_slots[i].sl_node_num)) { 24162306a36Sopenharmony_ci ret = i; 24262306a36Sopenharmony_ci break; 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci return ret; 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistatic int __ocfs2_find_empty_slot(struct ocfs2_slot_info *si, 25062306a36Sopenharmony_ci int preferred) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci int i, ret = -ENOSPC; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci if ((preferred >= 0) && (preferred < si->si_num_slots)) { 25562306a36Sopenharmony_ci if (!si->si_slots[preferred].sl_valid) { 25662306a36Sopenharmony_ci ret = preferred; 25762306a36Sopenharmony_ci goto out; 25862306a36Sopenharmony_ci } 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci for(i = 0; i < si->si_num_slots; i++) { 26262306a36Sopenharmony_ci if (!si->si_slots[i].sl_valid) { 26362306a36Sopenharmony_ci ret = i; 26462306a36Sopenharmony_ci break; 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ciout: 26862306a36Sopenharmony_ci return ret; 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ciint ocfs2_node_num_to_slot(struct ocfs2_super *osb, unsigned int node_num) 27262306a36Sopenharmony_ci{ 27362306a36Sopenharmony_ci int slot; 27462306a36Sopenharmony_ci struct ocfs2_slot_info *si = osb->slot_info; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci spin_lock(&osb->osb_lock); 27762306a36Sopenharmony_ci slot = __ocfs2_node_num_to_slot(si, node_num); 27862306a36Sopenharmony_ci spin_unlock(&osb->osb_lock); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci return slot; 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ciint ocfs2_slot_to_node_num_locked(struct ocfs2_super *osb, int slot_num, 28462306a36Sopenharmony_ci unsigned int *node_num) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci struct ocfs2_slot_info *si = osb->slot_info; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci assert_spin_locked(&osb->osb_lock); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci BUG_ON(slot_num < 0); 29162306a36Sopenharmony_ci BUG_ON(slot_num >= osb->max_slots); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci if (!si->si_slots[slot_num].sl_valid) 29462306a36Sopenharmony_ci return -ENOENT; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci *node_num = si->si_slots[slot_num].sl_node_num; 29762306a36Sopenharmony_ci return 0; 29862306a36Sopenharmony_ci} 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_cistatic void __ocfs2_free_slot_info(struct ocfs2_slot_info *si) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci unsigned int i; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci if (si == NULL) 30562306a36Sopenharmony_ci return; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci iput(si->si_inode); 30862306a36Sopenharmony_ci if (si->si_bh) { 30962306a36Sopenharmony_ci for (i = 0; i < si->si_blocks; i++) { 31062306a36Sopenharmony_ci if (si->si_bh[i]) { 31162306a36Sopenharmony_ci brelse(si->si_bh[i]); 31262306a36Sopenharmony_ci si->si_bh[i] = NULL; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci kfree(si->si_bh); 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci kfree(si); 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ciint ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci struct ocfs2_slot_info *si = osb->slot_info; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci if (si == NULL) 32662306a36Sopenharmony_ci return 0; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci spin_lock(&osb->osb_lock); 32962306a36Sopenharmony_ci ocfs2_invalidate_slot(si, slot_num); 33062306a36Sopenharmony_ci spin_unlock(&osb->osb_lock); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci return ocfs2_update_disk_slot(osb, osb->slot_info, slot_num); 33362306a36Sopenharmony_ci} 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_cistatic int ocfs2_map_slot_buffers(struct ocfs2_super *osb, 33662306a36Sopenharmony_ci struct ocfs2_slot_info *si) 33762306a36Sopenharmony_ci{ 33862306a36Sopenharmony_ci int status = 0; 33962306a36Sopenharmony_ci u64 blkno; 34062306a36Sopenharmony_ci unsigned long long blocks, bytes = 0; 34162306a36Sopenharmony_ci unsigned int i; 34262306a36Sopenharmony_ci struct buffer_head *bh; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci status = ocfs2_slot_map_physical_size(osb, si->si_inode, &bytes); 34562306a36Sopenharmony_ci if (status) 34662306a36Sopenharmony_ci goto bail; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci blocks = ocfs2_blocks_for_bytes(si->si_inode->i_sb, bytes); 34962306a36Sopenharmony_ci BUG_ON(blocks > UINT_MAX); 35062306a36Sopenharmony_ci si->si_blocks = blocks; 35162306a36Sopenharmony_ci if (!si->si_blocks) 35262306a36Sopenharmony_ci goto bail; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci if (si->si_extended) 35562306a36Sopenharmony_ci si->si_slots_per_block = 35662306a36Sopenharmony_ci (osb->sb->s_blocksize / 35762306a36Sopenharmony_ci sizeof(struct ocfs2_extended_slot)); 35862306a36Sopenharmony_ci else 35962306a36Sopenharmony_ci si->si_slots_per_block = osb->sb->s_blocksize / sizeof(__le16); 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci /* The size checks above should ensure this */ 36262306a36Sopenharmony_ci BUG_ON((osb->max_slots / si->si_slots_per_block) > blocks); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci trace_ocfs2_map_slot_buffers(bytes, si->si_blocks); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci si->si_bh = kcalloc(si->si_blocks, sizeof(struct buffer_head *), 36762306a36Sopenharmony_ci GFP_KERNEL); 36862306a36Sopenharmony_ci if (!si->si_bh) { 36962306a36Sopenharmony_ci status = -ENOMEM; 37062306a36Sopenharmony_ci mlog_errno(status); 37162306a36Sopenharmony_ci goto bail; 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci for (i = 0; i < si->si_blocks; i++) { 37562306a36Sopenharmony_ci status = ocfs2_extent_map_get_blocks(si->si_inode, i, 37662306a36Sopenharmony_ci &blkno, NULL, NULL); 37762306a36Sopenharmony_ci if (status < 0) { 37862306a36Sopenharmony_ci mlog_errno(status); 37962306a36Sopenharmony_ci goto bail; 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci trace_ocfs2_map_slot_buffers_block((unsigned long long)blkno, i); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci bh = NULL; /* Acquire a fresh bh */ 38562306a36Sopenharmony_ci status = ocfs2_read_blocks(INODE_CACHE(si->si_inode), blkno, 38662306a36Sopenharmony_ci 1, &bh, OCFS2_BH_IGNORE_CACHE, NULL); 38762306a36Sopenharmony_ci if (status < 0) { 38862306a36Sopenharmony_ci mlog_errno(status); 38962306a36Sopenharmony_ci goto bail; 39062306a36Sopenharmony_ci } 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci si->si_bh[i] = bh; 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_cibail: 39662306a36Sopenharmony_ci return status; 39762306a36Sopenharmony_ci} 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ciint ocfs2_init_slot_info(struct ocfs2_super *osb) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci int status; 40262306a36Sopenharmony_ci struct inode *inode = NULL; 40362306a36Sopenharmony_ci struct ocfs2_slot_info *si; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci si = kzalloc(struct_size(si, si_slots, osb->max_slots), GFP_KERNEL); 40662306a36Sopenharmony_ci if (!si) { 40762306a36Sopenharmony_ci status = -ENOMEM; 40862306a36Sopenharmony_ci mlog_errno(status); 40962306a36Sopenharmony_ci return status; 41062306a36Sopenharmony_ci } 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci si->si_extended = ocfs2_uses_extended_slot_map(osb); 41362306a36Sopenharmony_ci si->si_num_slots = osb->max_slots; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci inode = ocfs2_get_system_file_inode(osb, SLOT_MAP_SYSTEM_INODE, 41662306a36Sopenharmony_ci OCFS2_INVALID_SLOT); 41762306a36Sopenharmony_ci if (!inode) { 41862306a36Sopenharmony_ci status = -EINVAL; 41962306a36Sopenharmony_ci mlog_errno(status); 42062306a36Sopenharmony_ci goto bail; 42162306a36Sopenharmony_ci } 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci si->si_inode = inode; 42462306a36Sopenharmony_ci status = ocfs2_map_slot_buffers(osb, si); 42562306a36Sopenharmony_ci if (status < 0) { 42662306a36Sopenharmony_ci mlog_errno(status); 42762306a36Sopenharmony_ci goto bail; 42862306a36Sopenharmony_ci } 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci osb->slot_info = (struct ocfs2_slot_info *)si; 43162306a36Sopenharmony_cibail: 43262306a36Sopenharmony_ci if (status < 0) 43362306a36Sopenharmony_ci __ocfs2_free_slot_info(si); 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci return status; 43662306a36Sopenharmony_ci} 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_civoid ocfs2_free_slot_info(struct ocfs2_super *osb) 43962306a36Sopenharmony_ci{ 44062306a36Sopenharmony_ci struct ocfs2_slot_info *si = osb->slot_info; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci osb->slot_info = NULL; 44362306a36Sopenharmony_ci __ocfs2_free_slot_info(si); 44462306a36Sopenharmony_ci} 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ciint ocfs2_find_slot(struct ocfs2_super *osb) 44762306a36Sopenharmony_ci{ 44862306a36Sopenharmony_ci int status; 44962306a36Sopenharmony_ci int slot; 45062306a36Sopenharmony_ci struct ocfs2_slot_info *si; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci si = osb->slot_info; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci spin_lock(&osb->osb_lock); 45562306a36Sopenharmony_ci ocfs2_update_slot_info(si); 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci /* search for ourselves first and take the slot if it already 45862306a36Sopenharmony_ci * exists. Perhaps we need to mark this in a variable for our 45962306a36Sopenharmony_ci * own journal recovery? Possibly not, though we certainly 46062306a36Sopenharmony_ci * need to warn to the user */ 46162306a36Sopenharmony_ci slot = __ocfs2_node_num_to_slot(si, osb->node_num); 46262306a36Sopenharmony_ci if (slot < 0) { 46362306a36Sopenharmony_ci /* if no slot yet, then just take 1st available 46462306a36Sopenharmony_ci * one. */ 46562306a36Sopenharmony_ci slot = __ocfs2_find_empty_slot(si, osb->preferred_slot); 46662306a36Sopenharmony_ci if (slot < 0) { 46762306a36Sopenharmony_ci spin_unlock(&osb->osb_lock); 46862306a36Sopenharmony_ci mlog(ML_ERROR, "no free slots available!\n"); 46962306a36Sopenharmony_ci status = -EINVAL; 47062306a36Sopenharmony_ci goto bail; 47162306a36Sopenharmony_ci } 47262306a36Sopenharmony_ci } else 47362306a36Sopenharmony_ci printk(KERN_INFO "ocfs2: Slot %d on device (%s) was already " 47462306a36Sopenharmony_ci "allocated to this node!\n", slot, osb->dev_str); 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci ocfs2_set_slot(si, slot, osb->node_num); 47762306a36Sopenharmony_ci osb->slot_num = slot; 47862306a36Sopenharmony_ci spin_unlock(&osb->osb_lock); 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci trace_ocfs2_find_slot(osb->slot_num); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci status = ocfs2_update_disk_slot(osb, si, osb->slot_num); 48362306a36Sopenharmony_ci if (status < 0) { 48462306a36Sopenharmony_ci mlog_errno(status); 48562306a36Sopenharmony_ci /* 48662306a36Sopenharmony_ci * if write block failed, invalidate slot to avoid overwrite 48762306a36Sopenharmony_ci * slot during dismount in case another node rightly has mounted 48862306a36Sopenharmony_ci */ 48962306a36Sopenharmony_ci spin_lock(&osb->osb_lock); 49062306a36Sopenharmony_ci ocfs2_invalidate_slot(si, osb->slot_num); 49162306a36Sopenharmony_ci osb->slot_num = OCFS2_INVALID_SLOT; 49262306a36Sopenharmony_ci spin_unlock(&osb->osb_lock); 49362306a36Sopenharmony_ci } 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_cibail: 49662306a36Sopenharmony_ci return status; 49762306a36Sopenharmony_ci} 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_civoid ocfs2_put_slot(struct ocfs2_super *osb) 50062306a36Sopenharmony_ci{ 50162306a36Sopenharmony_ci int status, slot_num; 50262306a36Sopenharmony_ci struct ocfs2_slot_info *si = osb->slot_info; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci if (!si) 50562306a36Sopenharmony_ci return; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci spin_lock(&osb->osb_lock); 50862306a36Sopenharmony_ci ocfs2_update_slot_info(si); 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci slot_num = osb->slot_num; 51162306a36Sopenharmony_ci ocfs2_invalidate_slot(si, osb->slot_num); 51262306a36Sopenharmony_ci osb->slot_num = OCFS2_INVALID_SLOT; 51362306a36Sopenharmony_ci spin_unlock(&osb->osb_lock); 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci status = ocfs2_update_disk_slot(osb, si, slot_num); 51662306a36Sopenharmony_ci if (status < 0) 51762306a36Sopenharmony_ci mlog_errno(status); 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci ocfs2_free_slot_info(osb); 52062306a36Sopenharmony_ci} 521