1ccd979bdSMark Fasheh /* -*- mode: c; c-basic-offset: 8; -*- 2ccd979bdSMark Fasheh * vim: noexpandtab sw=8 ts=8 sts=0: 3ccd979bdSMark Fasheh * 4ccd979bdSMark Fasheh * slot_map.c 5ccd979bdSMark Fasheh * 6ccd979bdSMark Fasheh * 7ccd979bdSMark Fasheh * 8ccd979bdSMark Fasheh * Copyright (C) 2002, 2004 Oracle. All rights reserved. 9ccd979bdSMark Fasheh * 10ccd979bdSMark Fasheh * This program is free software; you can redistribute it and/or 11ccd979bdSMark Fasheh * modify it under the terms of the GNU General Public 12ccd979bdSMark Fasheh * License as published by the Free Software Foundation; either 13ccd979bdSMark Fasheh * version 2 of the License, or (at your option) any later version. 14ccd979bdSMark Fasheh * 15ccd979bdSMark Fasheh * This program is distributed in the hope that it will be useful, 16ccd979bdSMark Fasheh * but WITHOUT ANY WARRANTY; without even the implied warranty of 17ccd979bdSMark Fasheh * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18ccd979bdSMark Fasheh * General Public License for more details. 19ccd979bdSMark Fasheh * 20ccd979bdSMark Fasheh * You should have received a copy of the GNU General Public 21ccd979bdSMark Fasheh * License along with this program; if not, write to the 22ccd979bdSMark Fasheh * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 23ccd979bdSMark Fasheh * Boston, MA 021110-1307, USA. 24ccd979bdSMark Fasheh */ 25ccd979bdSMark Fasheh 26ccd979bdSMark Fasheh #include <linux/types.h> 27ccd979bdSMark Fasheh #include <linux/slab.h> 28ccd979bdSMark Fasheh #include <linux/highmem.h> 29ccd979bdSMark Fasheh 30ccd979bdSMark Fasheh #define MLOG_MASK_PREFIX ML_SUPER 31ccd979bdSMark Fasheh #include <cluster/masklog.h> 32ccd979bdSMark Fasheh 33ccd979bdSMark Fasheh #include "ocfs2.h" 34ccd979bdSMark Fasheh 35ccd979bdSMark Fasheh #include "dlmglue.h" 36ccd979bdSMark Fasheh #include "extent_map.h" 37ccd979bdSMark Fasheh #include "heartbeat.h" 38ccd979bdSMark Fasheh #include "inode.h" 39ccd979bdSMark Fasheh #include "slot_map.h" 40ccd979bdSMark Fasheh #include "super.h" 41ccd979bdSMark Fasheh #include "sysfile.h" 42ccd979bdSMark Fasheh 43ccd979bdSMark Fasheh #include "buffer_head_io.h" 44ccd979bdSMark Fasheh 45fc881fa0SJoel Becker 46fc881fa0SJoel Becker struct ocfs2_slot { 47fc881fa0SJoel Becker int sl_valid; 48fc881fa0SJoel Becker unsigned int sl_node_num; 49fc881fa0SJoel Becker }; 50fc881fa0SJoel Becker 51d85b20e4SJoel Becker struct ocfs2_slot_info { 52*386a2ef8SJoel Becker int si_extended; 53*386a2ef8SJoel Becker int si_slots_per_block; 54d85b20e4SJoel Becker struct inode *si_inode; 551c8d9a6aSJoel Becker unsigned int si_blocks; 561c8d9a6aSJoel Becker struct buffer_head **si_bh; 57d85b20e4SJoel Becker unsigned int si_num_slots; 58fc881fa0SJoel Becker struct ocfs2_slot *si_slots; 59d85b20e4SJoel Becker }; 60d85b20e4SJoel Becker 61d85b20e4SJoel Becker 62fc881fa0SJoel Becker static int __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si, 63fc881fa0SJoel Becker unsigned int node_num); 64fc881fa0SJoel Becker 65fc881fa0SJoel Becker static void ocfs2_invalidate_slot(struct ocfs2_slot_info *si, 66fc881fa0SJoel Becker int slot_num) 67fc881fa0SJoel Becker { 68fc881fa0SJoel Becker BUG_ON((slot_num < 0) || (slot_num >= si->si_num_slots)); 69fc881fa0SJoel Becker si->si_slots[slot_num].sl_valid = 0; 70fc881fa0SJoel Becker } 71fc881fa0SJoel Becker 72fc881fa0SJoel Becker static void ocfs2_set_slot(struct ocfs2_slot_info *si, 73fc881fa0SJoel Becker int slot_num, unsigned int node_num) 74fc881fa0SJoel Becker { 75fc881fa0SJoel Becker BUG_ON((slot_num < 0) || (slot_num >= si->si_num_slots)); 76fc881fa0SJoel Becker BUG_ON((node_num == O2NM_INVALID_NODE_NUM) || 77fc881fa0SJoel Becker (node_num >= O2NM_MAX_NODES)); 78fc881fa0SJoel Becker 79fc881fa0SJoel Becker si->si_slots[slot_num].sl_valid = 1; 80fc881fa0SJoel Becker si->si_slots[slot_num].sl_node_num = node_num; 81fc881fa0SJoel Becker } 82ccd979bdSMark Fasheh 83*386a2ef8SJoel Becker /* This version is for the extended slot map */ 84*386a2ef8SJoel Becker static void ocfs2_update_slot_info_extended(struct ocfs2_slot_info *si) 85*386a2ef8SJoel Becker { 86*386a2ef8SJoel Becker int b, i, slotno; 87*386a2ef8SJoel Becker struct ocfs2_slot_map_extended *se; 88*386a2ef8SJoel Becker 89*386a2ef8SJoel Becker slotno = 0; 90*386a2ef8SJoel Becker for (b = 0; b < si->si_blocks; b++) { 91*386a2ef8SJoel Becker se = (struct ocfs2_slot_map_extended *)si->si_bh[b]->b_data; 92*386a2ef8SJoel Becker for (i = 0; 93*386a2ef8SJoel Becker (i < si->si_slots_per_block) && 94*386a2ef8SJoel Becker (slotno < si->si_num_slots); 95*386a2ef8SJoel Becker i++, slotno++) { 96*386a2ef8SJoel Becker if (se->se_slots[i].es_valid) 97*386a2ef8SJoel Becker ocfs2_set_slot(si, slotno, 98*386a2ef8SJoel Becker le32_to_cpu(se->se_slots[i].es_node_num)); 99*386a2ef8SJoel Becker else 100*386a2ef8SJoel Becker ocfs2_invalidate_slot(si, slotno); 101*386a2ef8SJoel Becker } 102*386a2ef8SJoel Becker } 103*386a2ef8SJoel Becker } 104*386a2ef8SJoel Becker 105d85b20e4SJoel Becker /* 106d85b20e4SJoel Becker * Post the slot information on disk into our slot_info struct. 107d85b20e4SJoel Becker * Must be protected by osb_lock. 108d85b20e4SJoel Becker */ 109*386a2ef8SJoel Becker static void ocfs2_update_slot_info_old(struct ocfs2_slot_info *si) 110ccd979bdSMark Fasheh { 111ccd979bdSMark Fasheh int i; 112fb86b1f0SJoel Becker struct ocfs2_slot_map *sm; 113ccd979bdSMark Fasheh 114fb86b1f0SJoel Becker sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data; 115ccd979bdSMark Fasheh 116fc881fa0SJoel Becker for (i = 0; i < si->si_num_slots; i++) { 117fb86b1f0SJoel Becker if (le16_to_cpu(sm->sm_slots[i]) == (u16)OCFS2_INVALID_SLOT) 118fc881fa0SJoel Becker ocfs2_invalidate_slot(si, i); 119fc881fa0SJoel Becker else 120fb86b1f0SJoel Becker ocfs2_set_slot(si, i, le16_to_cpu(sm->sm_slots[i])); 121fc881fa0SJoel Becker } 122ccd979bdSMark Fasheh } 123ccd979bdSMark Fasheh 124*386a2ef8SJoel Becker static void ocfs2_update_slot_info(struct ocfs2_slot_info *si) 125*386a2ef8SJoel Becker { 126*386a2ef8SJoel Becker /* 127*386a2ef8SJoel Becker * The slot data will have been refreshed when ocfs2_super_lock 128*386a2ef8SJoel Becker * was taken. 129*386a2ef8SJoel Becker */ 130*386a2ef8SJoel Becker if (si->si_extended) 131*386a2ef8SJoel Becker ocfs2_update_slot_info_extended(si); 132*386a2ef8SJoel Becker else 133*386a2ef8SJoel Becker ocfs2_update_slot_info_old(si); 134*386a2ef8SJoel Becker } 135*386a2ef8SJoel Becker 1368e8a4603SMark Fasheh int ocfs2_refresh_slot_info(struct ocfs2_super *osb) 1378e8a4603SMark Fasheh { 1388e8a4603SMark Fasheh int ret; 1398e8a4603SMark Fasheh struct ocfs2_slot_info *si = osb->slot_info; 1408e8a4603SMark Fasheh 1418e8a4603SMark Fasheh if (si == NULL) 1428e8a4603SMark Fasheh return 0; 1438e8a4603SMark Fasheh 1441c8d9a6aSJoel Becker BUG_ON(si->si_blocks == 0); 1451c8d9a6aSJoel Becker BUG_ON(si->si_bh == NULL); 1461c8d9a6aSJoel Becker 1471c8d9a6aSJoel Becker mlog(0, "Refreshing slot map, reading %u block(s)\n", 1481c8d9a6aSJoel Becker si->si_blocks); 1491c8d9a6aSJoel Becker 1501c8d9a6aSJoel Becker /* 1511c8d9a6aSJoel Becker * We pass -1 as blocknr because we expect all of si->si_bh to 1521c8d9a6aSJoel Becker * be !NULL. Thus, ocfs2_read_blocks() will ignore blocknr. If 1531c8d9a6aSJoel Becker * this is not true, the read of -1 (UINT64_MAX) will fail. 1541c8d9a6aSJoel Becker */ 1551c8d9a6aSJoel Becker ret = ocfs2_read_blocks(osb, -1, si->si_blocks, si->si_bh, 0, 1561c8d9a6aSJoel Becker si->si_inode); 157d85b20e4SJoel Becker if (ret == 0) { 158d85b20e4SJoel Becker spin_lock(&osb->osb_lock); 1598e8a4603SMark Fasheh ocfs2_update_slot_info(si); 160d85b20e4SJoel Becker spin_unlock(&osb->osb_lock); 161d85b20e4SJoel Becker } 1628e8a4603SMark Fasheh 1638e8a4603SMark Fasheh return ret; 1648e8a4603SMark Fasheh } 1658e8a4603SMark Fasheh 166ccd979bdSMark Fasheh /* post the our slot info stuff into it's destination bh and write it 167ccd979bdSMark Fasheh * out. */ 168*386a2ef8SJoel Becker static void ocfs2_update_disk_slot_extended(struct ocfs2_slot_info *si, 169*386a2ef8SJoel Becker int slot_num, 170*386a2ef8SJoel Becker struct buffer_head **bh) 171ccd979bdSMark Fasheh { 172*386a2ef8SJoel Becker int blkind = slot_num / si->si_slots_per_block; 173*386a2ef8SJoel Becker int slotno = slot_num % si->si_slots_per_block; 174*386a2ef8SJoel Becker struct ocfs2_slot_map_extended *se; 175*386a2ef8SJoel Becker 176*386a2ef8SJoel Becker BUG_ON(blkind >= si->si_blocks); 177*386a2ef8SJoel Becker 178*386a2ef8SJoel Becker se = (struct ocfs2_slot_map_extended *)si->si_bh[blkind]->b_data; 179*386a2ef8SJoel Becker se->se_slots[slotno].es_valid = si->si_slots[slot_num].sl_valid; 180*386a2ef8SJoel Becker if (si->si_slots[slot_num].sl_valid) 181*386a2ef8SJoel Becker se->se_slots[slotno].es_node_num = 182*386a2ef8SJoel Becker cpu_to_le32(si->si_slots[slot_num].sl_node_num); 183*386a2ef8SJoel Becker *bh = si->si_bh[blkind]; 184*386a2ef8SJoel Becker } 185*386a2ef8SJoel Becker 186*386a2ef8SJoel Becker static void ocfs2_update_disk_slot_old(struct ocfs2_slot_info *si, 187*386a2ef8SJoel Becker int slot_num, 188*386a2ef8SJoel Becker struct buffer_head **bh) 189*386a2ef8SJoel Becker { 190*386a2ef8SJoel Becker int i; 191fb86b1f0SJoel Becker struct ocfs2_slot_map *sm; 192ccd979bdSMark Fasheh 193fb86b1f0SJoel Becker sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data; 194fc881fa0SJoel Becker for (i = 0; i < si->si_num_slots; i++) { 195fc881fa0SJoel Becker if (si->si_slots[i].sl_valid) 196fb86b1f0SJoel Becker sm->sm_slots[i] = 197fc881fa0SJoel Becker cpu_to_le16(si->si_slots[i].sl_node_num); 198fc881fa0SJoel Becker else 199fb86b1f0SJoel Becker sm->sm_slots[i] = cpu_to_le16(OCFS2_INVALID_SLOT); 200fc881fa0SJoel Becker } 201*386a2ef8SJoel Becker *bh = si->si_bh[0]; 202*386a2ef8SJoel Becker } 203*386a2ef8SJoel Becker 204*386a2ef8SJoel Becker static int ocfs2_update_disk_slot(struct ocfs2_super *osb, 205*386a2ef8SJoel Becker struct ocfs2_slot_info *si, 206*386a2ef8SJoel Becker int slot_num) 207*386a2ef8SJoel Becker { 208*386a2ef8SJoel Becker int status; 209*386a2ef8SJoel Becker struct buffer_head *bh; 210*386a2ef8SJoel Becker 211*386a2ef8SJoel Becker spin_lock(&osb->osb_lock); 212*386a2ef8SJoel Becker if (si->si_extended) 213*386a2ef8SJoel Becker ocfs2_update_disk_slot_extended(si, slot_num, &bh); 214*386a2ef8SJoel Becker else 215*386a2ef8SJoel Becker ocfs2_update_disk_slot_old(si, slot_num, &bh); 216d85b20e4SJoel Becker spin_unlock(&osb->osb_lock); 217ccd979bdSMark Fasheh 218*386a2ef8SJoel Becker status = ocfs2_write_block(osb, bh, si->si_inode); 219ccd979bdSMark Fasheh if (status < 0) 220ccd979bdSMark Fasheh mlog_errno(status); 221ccd979bdSMark Fasheh 222ccd979bdSMark Fasheh return status; 223ccd979bdSMark Fasheh } 224ccd979bdSMark Fasheh 2251c8d9a6aSJoel Becker /* 2261c8d9a6aSJoel Becker * Calculate how many bytes are needed by the slot map. Returns 2271c8d9a6aSJoel Becker * an error if the slot map file is too small. 2281c8d9a6aSJoel Becker */ 2291c8d9a6aSJoel Becker static int ocfs2_slot_map_physical_size(struct ocfs2_super *osb, 2301c8d9a6aSJoel Becker struct inode *inode, 2311c8d9a6aSJoel Becker unsigned long long *bytes) 2321c8d9a6aSJoel Becker { 2331c8d9a6aSJoel Becker unsigned long long bytes_needed; 2341c8d9a6aSJoel Becker 235*386a2ef8SJoel Becker if (ocfs2_uses_extended_slot_map(osb)) { 236*386a2ef8SJoel Becker bytes_needed = osb->max_slots * 237*386a2ef8SJoel Becker sizeof(struct ocfs2_extended_slot); 238*386a2ef8SJoel Becker } else { 2391c8d9a6aSJoel Becker bytes_needed = osb->max_slots * sizeof(__le16); 240*386a2ef8SJoel Becker } 2411c8d9a6aSJoel Becker if (bytes_needed > i_size_read(inode)) { 2421c8d9a6aSJoel Becker mlog(ML_ERROR, 2431c8d9a6aSJoel Becker "Slot map file is too small! (size %llu, needed %llu)\n", 2441c8d9a6aSJoel Becker i_size_read(inode), bytes_needed); 2451c8d9a6aSJoel Becker return -ENOSPC; 2461c8d9a6aSJoel Becker } 2471c8d9a6aSJoel Becker 2481c8d9a6aSJoel Becker *bytes = bytes_needed; 2491c8d9a6aSJoel Becker return 0; 2501c8d9a6aSJoel Becker } 2511c8d9a6aSJoel Becker 252fc881fa0SJoel Becker /* try to find global node in the slot info. Returns -ENOENT 253fc881fa0SJoel Becker * if nothing is found. */ 254fc881fa0SJoel Becker static int __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si, 255fc881fa0SJoel Becker unsigned int node_num) 256ccd979bdSMark Fasheh { 257fc881fa0SJoel Becker int i, ret = -ENOENT; 258ccd979bdSMark Fasheh 259ccd979bdSMark Fasheh for(i = 0; i < si->si_num_slots; i++) { 260fc881fa0SJoel Becker if (si->si_slots[i].sl_valid && 261fc881fa0SJoel Becker (node_num == si->si_slots[i].sl_node_num)) { 262fc881fa0SJoel Becker ret = i; 263ccd979bdSMark Fasheh break; 264ccd979bdSMark Fasheh } 265ccd979bdSMark Fasheh } 266fc881fa0SJoel Becker 267ccd979bdSMark Fasheh return ret; 268ccd979bdSMark Fasheh } 269ccd979bdSMark Fasheh 270fc881fa0SJoel Becker static int __ocfs2_find_empty_slot(struct ocfs2_slot_info *si, 271fc881fa0SJoel Becker int preferred) 272ccd979bdSMark Fasheh { 273fc881fa0SJoel Becker int i, ret = -ENOSPC; 274ccd979bdSMark Fasheh 275fc881fa0SJoel Becker if ((preferred >= 0) && (preferred < si->si_num_slots)) { 276fc881fa0SJoel Becker if (!si->si_slots[preferred].sl_valid) { 277baf4661aSSunil Mushran ret = preferred; 278baf4661aSSunil Mushran goto out; 279baf4661aSSunil Mushran } 280baf4661aSSunil Mushran } 281baf4661aSSunil Mushran 282ccd979bdSMark Fasheh for(i = 0; i < si->si_num_slots; i++) { 283fc881fa0SJoel Becker if (!si->si_slots[i].sl_valid) { 284fc881fa0SJoel Becker ret = i; 285ccd979bdSMark Fasheh break; 286ccd979bdSMark Fasheh } 287ccd979bdSMark Fasheh } 288baf4661aSSunil Mushran out: 289ccd979bdSMark Fasheh return ret; 290ccd979bdSMark Fasheh } 291ccd979bdSMark Fasheh 292d85b20e4SJoel Becker int ocfs2_node_num_to_slot(struct ocfs2_super *osb, unsigned int node_num) 293ccd979bdSMark Fasheh { 294fc881fa0SJoel Becker int slot; 295d85b20e4SJoel Becker struct ocfs2_slot_info *si = osb->slot_info; 296ccd979bdSMark Fasheh 297d85b20e4SJoel Becker spin_lock(&osb->osb_lock); 298d85b20e4SJoel Becker slot = __ocfs2_node_num_to_slot(si, node_num); 299d85b20e4SJoel Becker spin_unlock(&osb->osb_lock); 300d85b20e4SJoel Becker 301d85b20e4SJoel Becker return slot; 302d85b20e4SJoel Becker } 303d85b20e4SJoel Becker 304d85b20e4SJoel Becker int ocfs2_slot_to_node_num_locked(struct ocfs2_super *osb, int slot_num, 305d85b20e4SJoel Becker unsigned int *node_num) 306d85b20e4SJoel Becker { 307d85b20e4SJoel Becker struct ocfs2_slot_info *si = osb->slot_info; 308d85b20e4SJoel Becker 309d85b20e4SJoel Becker assert_spin_locked(&osb->osb_lock); 310d85b20e4SJoel Becker 311d85b20e4SJoel Becker BUG_ON(slot_num < 0); 312d85b20e4SJoel Becker BUG_ON(slot_num > osb->max_slots); 313d85b20e4SJoel Becker 314fc881fa0SJoel Becker if (!si->si_slots[slot_num].sl_valid) 315d85b20e4SJoel Becker return -ENOENT; 316d85b20e4SJoel Becker 317fc881fa0SJoel Becker *node_num = si->si_slots[slot_num].sl_node_num; 318d85b20e4SJoel Becker return 0; 319ccd979bdSMark Fasheh } 320ccd979bdSMark Fasheh 3218e8a4603SMark Fasheh static void __ocfs2_free_slot_info(struct ocfs2_slot_info *si) 3228e8a4603SMark Fasheh { 3231c8d9a6aSJoel Becker unsigned int i; 3241c8d9a6aSJoel Becker 3258e8a4603SMark Fasheh if (si == NULL) 3268e8a4603SMark Fasheh return; 3278e8a4603SMark Fasheh 3288e8a4603SMark Fasheh if (si->si_inode) 3298e8a4603SMark Fasheh iput(si->si_inode); 3301c8d9a6aSJoel Becker if (si->si_bh) { 3311c8d9a6aSJoel Becker for (i = 0; i < si->si_blocks; i++) { 3321c8d9a6aSJoel Becker if (si->si_bh[i]) { 3331c8d9a6aSJoel Becker brelse(si->si_bh[i]); 3341c8d9a6aSJoel Becker si->si_bh[i] = NULL; 3351c8d9a6aSJoel Becker } 3361c8d9a6aSJoel Becker } 3371c8d9a6aSJoel Becker kfree(si->si_bh); 3381c8d9a6aSJoel Becker } 3398e8a4603SMark Fasheh 3408e8a4603SMark Fasheh kfree(si); 3418e8a4603SMark Fasheh } 3428e8a4603SMark Fasheh 343fc881fa0SJoel Becker int ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num) 344ccd979bdSMark Fasheh { 3458e8a4603SMark Fasheh struct ocfs2_slot_info *si = osb->slot_info; 3468e8a4603SMark Fasheh 3478e8a4603SMark Fasheh if (si == NULL) 3488e8a4603SMark Fasheh return 0; 3498e8a4603SMark Fasheh 350d85b20e4SJoel Becker spin_lock(&osb->osb_lock); 351fc881fa0SJoel Becker ocfs2_invalidate_slot(si, slot_num); 352d85b20e4SJoel Becker spin_unlock(&osb->osb_lock); 3538e8a4603SMark Fasheh 354*386a2ef8SJoel Becker return ocfs2_update_disk_slot(osb, osb->slot_info, slot_num); 355ccd979bdSMark Fasheh } 356ccd979bdSMark Fasheh 3571c8d9a6aSJoel Becker static int ocfs2_map_slot_buffers(struct ocfs2_super *osb, 3581c8d9a6aSJoel Becker struct ocfs2_slot_info *si) 3591c8d9a6aSJoel Becker { 3601c8d9a6aSJoel Becker int status = 0; 3611c8d9a6aSJoel Becker u64 blkno; 3621c8d9a6aSJoel Becker unsigned long long blocks, bytes; 3631c8d9a6aSJoel Becker unsigned int i; 3641c8d9a6aSJoel Becker struct buffer_head *bh; 3651c8d9a6aSJoel Becker 3661c8d9a6aSJoel Becker status = ocfs2_slot_map_physical_size(osb, si->si_inode, &bytes); 3671c8d9a6aSJoel Becker if (status) 3681c8d9a6aSJoel Becker goto bail; 3691c8d9a6aSJoel Becker 3701c8d9a6aSJoel Becker blocks = ocfs2_blocks_for_bytes(si->si_inode->i_sb, bytes); 3711c8d9a6aSJoel Becker BUG_ON(blocks > UINT_MAX); 3721c8d9a6aSJoel Becker si->si_blocks = blocks; 3731c8d9a6aSJoel Becker if (!si->si_blocks) 3741c8d9a6aSJoel Becker goto bail; 3751c8d9a6aSJoel Becker 376*386a2ef8SJoel Becker if (si->si_extended) 377*386a2ef8SJoel Becker si->si_slots_per_block = 378*386a2ef8SJoel Becker (osb->sb->s_blocksize / 379*386a2ef8SJoel Becker sizeof(struct ocfs2_extended_slot)); 380*386a2ef8SJoel Becker else 381*386a2ef8SJoel Becker si->si_slots_per_block = osb->sb->s_blocksize / sizeof(__le16); 382*386a2ef8SJoel Becker 383*386a2ef8SJoel Becker /* The size checks above should ensure this */ 384*386a2ef8SJoel Becker BUG_ON((osb->max_slots / si->si_slots_per_block) > blocks); 385*386a2ef8SJoel Becker 3861c8d9a6aSJoel Becker mlog(0, "Slot map needs %u buffers for %llu bytes\n", 3871c8d9a6aSJoel Becker si->si_blocks, bytes); 3881c8d9a6aSJoel Becker 3891c8d9a6aSJoel Becker si->si_bh = kzalloc(sizeof(struct buffer_head *) * si->si_blocks, 3901c8d9a6aSJoel Becker GFP_KERNEL); 3911c8d9a6aSJoel Becker if (!si->si_bh) { 3921c8d9a6aSJoel Becker status = -ENOMEM; 3931c8d9a6aSJoel Becker mlog_errno(status); 3941c8d9a6aSJoel Becker goto bail; 3951c8d9a6aSJoel Becker } 3961c8d9a6aSJoel Becker 3971c8d9a6aSJoel Becker for (i = 0; i < si->si_blocks; i++) { 3981c8d9a6aSJoel Becker status = ocfs2_extent_map_get_blocks(si->si_inode, i, 3991c8d9a6aSJoel Becker &blkno, NULL, NULL); 4001c8d9a6aSJoel Becker if (status < 0) { 4011c8d9a6aSJoel Becker mlog_errno(status); 4021c8d9a6aSJoel Becker goto bail; 4031c8d9a6aSJoel Becker } 4041c8d9a6aSJoel Becker 4051c8d9a6aSJoel Becker mlog(0, "Reading slot map block %u at %llu\n", i, 4061c8d9a6aSJoel Becker (unsigned long long)blkno); 4071c8d9a6aSJoel Becker 4081c8d9a6aSJoel Becker bh = NULL; /* Acquire a fresh bh */ 4091c8d9a6aSJoel Becker status = ocfs2_read_block(osb, blkno, &bh, 0, si->si_inode); 4101c8d9a6aSJoel Becker if (status < 0) { 4111c8d9a6aSJoel Becker mlog_errno(status); 4121c8d9a6aSJoel Becker goto bail; 4131c8d9a6aSJoel Becker } 4141c8d9a6aSJoel Becker 4151c8d9a6aSJoel Becker si->si_bh[i] = bh; 4161c8d9a6aSJoel Becker } 4171c8d9a6aSJoel Becker 4181c8d9a6aSJoel Becker bail: 4191c8d9a6aSJoel Becker return status; 4201c8d9a6aSJoel Becker } 4211c8d9a6aSJoel Becker 422ccd979bdSMark Fasheh int ocfs2_init_slot_info(struct ocfs2_super *osb) 423ccd979bdSMark Fasheh { 424fc881fa0SJoel Becker int status; 425ccd979bdSMark Fasheh struct inode *inode = NULL; 426ccd979bdSMark Fasheh struct ocfs2_slot_info *si; 427ccd979bdSMark Fasheh 428fc881fa0SJoel Becker si = kzalloc(sizeof(struct ocfs2_slot_info) + 429fc881fa0SJoel Becker (sizeof(struct ocfs2_slot) * osb->max_slots), 430fc881fa0SJoel Becker GFP_KERNEL); 431ccd979bdSMark Fasheh if (!si) { 432ccd979bdSMark Fasheh status = -ENOMEM; 433ccd979bdSMark Fasheh mlog_errno(status); 434ccd979bdSMark Fasheh goto bail; 435ccd979bdSMark Fasheh } 436ccd979bdSMark Fasheh 437*386a2ef8SJoel Becker si->si_extended = ocfs2_uses_extended_slot_map(osb); 438ccd979bdSMark Fasheh si->si_num_slots = osb->max_slots; 439fc881fa0SJoel Becker si->si_slots = (struct ocfs2_slot *)((char *)si + 440fc881fa0SJoel Becker sizeof(struct ocfs2_slot_info)); 441ccd979bdSMark Fasheh 442ccd979bdSMark Fasheh inode = ocfs2_get_system_file_inode(osb, SLOT_MAP_SYSTEM_INODE, 443ccd979bdSMark Fasheh OCFS2_INVALID_SLOT); 444ccd979bdSMark Fasheh if (!inode) { 445ccd979bdSMark Fasheh status = -EINVAL; 446ccd979bdSMark Fasheh mlog_errno(status); 447ccd979bdSMark Fasheh goto bail; 448ccd979bdSMark Fasheh } 449ccd979bdSMark Fasheh 450ccd979bdSMark Fasheh si->si_inode = inode; 4511c8d9a6aSJoel Becker status = ocfs2_map_slot_buffers(osb, si); 4521c8d9a6aSJoel Becker if (status < 0) { 4531c8d9a6aSJoel Becker mlog_errno(status); 4541c8d9a6aSJoel Becker goto bail; 4551c8d9a6aSJoel Becker } 4561c8d9a6aSJoel Becker 457d85b20e4SJoel Becker osb->slot_info = (struct ocfs2_slot_info *)si; 458ccd979bdSMark Fasheh bail: 459ccd979bdSMark Fasheh if (status < 0 && si) 4608e8a4603SMark Fasheh __ocfs2_free_slot_info(si); 461ccd979bdSMark Fasheh 462ccd979bdSMark Fasheh return status; 463ccd979bdSMark Fasheh } 464ccd979bdSMark Fasheh 4658e8a4603SMark Fasheh void ocfs2_free_slot_info(struct ocfs2_super *osb) 466ccd979bdSMark Fasheh { 4678e8a4603SMark Fasheh struct ocfs2_slot_info *si = osb->slot_info; 4688e8a4603SMark Fasheh 4698e8a4603SMark Fasheh osb->slot_info = NULL; 4708e8a4603SMark Fasheh __ocfs2_free_slot_info(si); 471ccd979bdSMark Fasheh } 472ccd979bdSMark Fasheh 473ccd979bdSMark Fasheh int ocfs2_find_slot(struct ocfs2_super *osb) 474ccd979bdSMark Fasheh { 475ccd979bdSMark Fasheh int status; 476fc881fa0SJoel Becker int slot; 477ccd979bdSMark Fasheh struct ocfs2_slot_info *si; 478ccd979bdSMark Fasheh 479ccd979bdSMark Fasheh mlog_entry_void(); 480ccd979bdSMark Fasheh 481ccd979bdSMark Fasheh si = osb->slot_info; 482ccd979bdSMark Fasheh 483d85b20e4SJoel Becker spin_lock(&osb->osb_lock); 484ccd979bdSMark Fasheh ocfs2_update_slot_info(si); 485ccd979bdSMark Fasheh 486ccd979bdSMark Fasheh /* search for ourselves first and take the slot if it already 487ccd979bdSMark Fasheh * exists. Perhaps we need to mark this in a variable for our 488ccd979bdSMark Fasheh * own journal recovery? Possibly not, though we certainly 489ccd979bdSMark Fasheh * need to warn to the user */ 490ccd979bdSMark Fasheh slot = __ocfs2_node_num_to_slot(si, osb->node_num); 491fc881fa0SJoel Becker if (slot < 0) { 492ccd979bdSMark Fasheh /* if no slot yet, then just take 1st available 493ccd979bdSMark Fasheh * one. */ 494baf4661aSSunil Mushran slot = __ocfs2_find_empty_slot(si, osb->preferred_slot); 495fc881fa0SJoel Becker if (slot < 0) { 496d85b20e4SJoel Becker spin_unlock(&osb->osb_lock); 497ccd979bdSMark Fasheh mlog(ML_ERROR, "no free slots available!\n"); 498ccd979bdSMark Fasheh status = -EINVAL; 499ccd979bdSMark Fasheh goto bail; 500ccd979bdSMark Fasheh } 501ccd979bdSMark Fasheh } else 502ccd979bdSMark Fasheh mlog(ML_NOTICE, "slot %d is already allocated to this node!\n", 503ccd979bdSMark Fasheh slot); 504ccd979bdSMark Fasheh 505fc881fa0SJoel Becker ocfs2_set_slot(si, slot, osb->node_num); 506ccd979bdSMark Fasheh osb->slot_num = slot; 507d85b20e4SJoel Becker spin_unlock(&osb->osb_lock); 508ccd979bdSMark Fasheh 509e7607ab3SMark Fasheh mlog(0, "taking node slot %d\n", osb->slot_num); 510ccd979bdSMark Fasheh 511*386a2ef8SJoel Becker status = ocfs2_update_disk_slot(osb, si, osb->slot_num); 512ccd979bdSMark Fasheh if (status < 0) 513ccd979bdSMark Fasheh mlog_errno(status); 514ccd979bdSMark Fasheh 515ccd979bdSMark Fasheh bail: 516ccd979bdSMark Fasheh mlog_exit(status); 517ccd979bdSMark Fasheh return status; 518ccd979bdSMark Fasheh } 519ccd979bdSMark Fasheh 520ccd979bdSMark Fasheh void ocfs2_put_slot(struct ocfs2_super *osb) 521ccd979bdSMark Fasheh { 522*386a2ef8SJoel Becker int status, slot_num; 523ccd979bdSMark Fasheh struct ocfs2_slot_info *si = osb->slot_info; 524ccd979bdSMark Fasheh 525ccd979bdSMark Fasheh if (!si) 526ccd979bdSMark Fasheh return; 527ccd979bdSMark Fasheh 528d85b20e4SJoel Becker spin_lock(&osb->osb_lock); 529ccd979bdSMark Fasheh ocfs2_update_slot_info(si); 530ccd979bdSMark Fasheh 531*386a2ef8SJoel Becker slot_num = osb->slot_num; 532fc881fa0SJoel Becker ocfs2_invalidate_slot(si, osb->slot_num); 533ccd979bdSMark Fasheh osb->slot_num = OCFS2_INVALID_SLOT; 534d85b20e4SJoel Becker spin_unlock(&osb->osb_lock); 535ccd979bdSMark Fasheh 536*386a2ef8SJoel Becker status = ocfs2_update_disk_slot(osb, si, slot_num); 537ccd979bdSMark Fasheh if (status < 0) { 538ccd979bdSMark Fasheh mlog_errno(status); 539ccd979bdSMark Fasheh goto bail; 540ccd979bdSMark Fasheh } 541ccd979bdSMark Fasheh 542ccd979bdSMark Fasheh bail: 5438e8a4603SMark Fasheh ocfs2_free_slot_info(osb); 544ccd979bdSMark Fasheh } 545ccd979bdSMark Fasheh 546