1328970deSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2*fa60ce2cSMasahiro Yamada /* 3ccd979bdSMark Fasheh * slot_map.c 4ccd979bdSMark Fasheh * 5ccd979bdSMark Fasheh * Copyright (C) 2002, 2004 Oracle. All rights reserved. 6ccd979bdSMark Fasheh */ 7ccd979bdSMark Fasheh 8ccd979bdSMark Fasheh #include <linux/types.h> 9ccd979bdSMark Fasheh #include <linux/slab.h> 10ccd979bdSMark Fasheh #include <linux/highmem.h> 11ccd979bdSMark Fasheh 12ccd979bdSMark Fasheh #include <cluster/masklog.h> 13ccd979bdSMark Fasheh 14ccd979bdSMark Fasheh #include "ocfs2.h" 15ccd979bdSMark Fasheh 16ccd979bdSMark Fasheh #include "dlmglue.h" 17ccd979bdSMark Fasheh #include "extent_map.h" 18ccd979bdSMark Fasheh #include "heartbeat.h" 19ccd979bdSMark Fasheh #include "inode.h" 20ccd979bdSMark Fasheh #include "slot_map.h" 21ccd979bdSMark Fasheh #include "super.h" 22ccd979bdSMark Fasheh #include "sysfile.h" 23a8731086STao Ma #include "ocfs2_trace.h" 24ccd979bdSMark Fasheh 25ccd979bdSMark Fasheh #include "buffer_head_io.h" 26ccd979bdSMark Fasheh 27fc881fa0SJoel Becker 28fc881fa0SJoel Becker struct ocfs2_slot { 29fc881fa0SJoel Becker int sl_valid; 30fc881fa0SJoel Becker unsigned int sl_node_num; 31fc881fa0SJoel Becker }; 32fc881fa0SJoel Becker 33d85b20e4SJoel Becker struct ocfs2_slot_info { 34386a2ef8SJoel Becker int si_extended; 35386a2ef8SJoel Becker int si_slots_per_block; 36d85b20e4SJoel Becker struct inode *si_inode; 371c8d9a6aSJoel Becker unsigned int si_blocks; 381c8d9a6aSJoel Becker struct buffer_head **si_bh; 39d85b20e4SJoel Becker unsigned int si_num_slots; 40f402cf03SGustavo A. R. Silva struct ocfs2_slot si_slots[]; 41d85b20e4SJoel Becker }; 42d85b20e4SJoel Becker 43d85b20e4SJoel Becker 44fc881fa0SJoel Becker static int __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si, 45fc881fa0SJoel Becker unsigned int node_num); 46fc881fa0SJoel Becker 47fc881fa0SJoel Becker static void ocfs2_invalidate_slot(struct ocfs2_slot_info *si, 48fc881fa0SJoel Becker int slot_num) 49fc881fa0SJoel Becker { 50fc881fa0SJoel Becker BUG_ON((slot_num < 0) || (slot_num >= si->si_num_slots)); 51fc881fa0SJoel Becker si->si_slots[slot_num].sl_valid = 0; 52fc881fa0SJoel Becker } 53fc881fa0SJoel Becker 54fc881fa0SJoel Becker static void ocfs2_set_slot(struct ocfs2_slot_info *si, 55fc881fa0SJoel Becker int slot_num, unsigned int node_num) 56fc881fa0SJoel Becker { 57fc881fa0SJoel Becker BUG_ON((slot_num < 0) || (slot_num >= si->si_num_slots)); 58fc881fa0SJoel Becker 59fc881fa0SJoel Becker si->si_slots[slot_num].sl_valid = 1; 60fc881fa0SJoel Becker si->si_slots[slot_num].sl_node_num = node_num; 61fc881fa0SJoel Becker } 62ccd979bdSMark Fasheh 63386a2ef8SJoel Becker /* This version is for the extended slot map */ 64386a2ef8SJoel Becker static void ocfs2_update_slot_info_extended(struct ocfs2_slot_info *si) 65386a2ef8SJoel Becker { 66386a2ef8SJoel Becker int b, i, slotno; 67386a2ef8SJoel Becker struct ocfs2_slot_map_extended *se; 68386a2ef8SJoel Becker 69386a2ef8SJoel Becker slotno = 0; 70386a2ef8SJoel Becker for (b = 0; b < si->si_blocks; b++) { 71386a2ef8SJoel Becker se = (struct ocfs2_slot_map_extended *)si->si_bh[b]->b_data; 72386a2ef8SJoel Becker for (i = 0; 73386a2ef8SJoel Becker (i < si->si_slots_per_block) && 74386a2ef8SJoel Becker (slotno < si->si_num_slots); 75386a2ef8SJoel Becker i++, slotno++) { 76386a2ef8SJoel Becker if (se->se_slots[i].es_valid) 77386a2ef8SJoel Becker ocfs2_set_slot(si, slotno, 78386a2ef8SJoel Becker le32_to_cpu(se->se_slots[i].es_node_num)); 79386a2ef8SJoel Becker else 80386a2ef8SJoel Becker ocfs2_invalidate_slot(si, slotno); 81386a2ef8SJoel Becker } 82386a2ef8SJoel Becker } 83386a2ef8SJoel Becker } 84386a2ef8SJoel Becker 85d85b20e4SJoel Becker /* 86d85b20e4SJoel Becker * Post the slot information on disk into our slot_info struct. 87d85b20e4SJoel Becker * Must be protected by osb_lock. 88d85b20e4SJoel Becker */ 89386a2ef8SJoel Becker static void ocfs2_update_slot_info_old(struct ocfs2_slot_info *si) 90ccd979bdSMark Fasheh { 91ccd979bdSMark Fasheh int i; 92fb86b1f0SJoel Becker struct ocfs2_slot_map *sm; 93ccd979bdSMark Fasheh 94fb86b1f0SJoel Becker sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data; 95ccd979bdSMark Fasheh 96fc881fa0SJoel Becker for (i = 0; i < si->si_num_slots; i++) { 97fb86b1f0SJoel Becker if (le16_to_cpu(sm->sm_slots[i]) == (u16)OCFS2_INVALID_SLOT) 98fc881fa0SJoel Becker ocfs2_invalidate_slot(si, i); 99fc881fa0SJoel Becker else 100fb86b1f0SJoel Becker ocfs2_set_slot(si, i, le16_to_cpu(sm->sm_slots[i])); 101fc881fa0SJoel Becker } 102ccd979bdSMark Fasheh } 103ccd979bdSMark Fasheh 104386a2ef8SJoel Becker static void ocfs2_update_slot_info(struct ocfs2_slot_info *si) 105386a2ef8SJoel Becker { 106386a2ef8SJoel Becker /* 107386a2ef8SJoel Becker * The slot data will have been refreshed when ocfs2_super_lock 108386a2ef8SJoel Becker * was taken. 109386a2ef8SJoel Becker */ 110386a2ef8SJoel Becker if (si->si_extended) 111386a2ef8SJoel Becker ocfs2_update_slot_info_extended(si); 112386a2ef8SJoel Becker else 113386a2ef8SJoel Becker ocfs2_update_slot_info_old(si); 114386a2ef8SJoel Becker } 115386a2ef8SJoel Becker 1168e8a4603SMark Fasheh int ocfs2_refresh_slot_info(struct ocfs2_super *osb) 1178e8a4603SMark Fasheh { 1188e8a4603SMark Fasheh int ret; 1198e8a4603SMark Fasheh struct ocfs2_slot_info *si = osb->slot_info; 1208e8a4603SMark Fasheh 1218e8a4603SMark Fasheh if (si == NULL) 1228e8a4603SMark Fasheh return 0; 1238e8a4603SMark Fasheh 1241c8d9a6aSJoel Becker BUG_ON(si->si_blocks == 0); 1251c8d9a6aSJoel Becker BUG_ON(si->si_bh == NULL); 1261c8d9a6aSJoel Becker 127a8731086STao Ma trace_ocfs2_refresh_slot_info(si->si_blocks); 1281c8d9a6aSJoel Becker 1291c8d9a6aSJoel Becker /* 1301c8d9a6aSJoel Becker * We pass -1 as blocknr because we expect all of si->si_bh to 1311c8d9a6aSJoel Becker * be !NULL. Thus, ocfs2_read_blocks() will ignore blocknr. If 1321c8d9a6aSJoel Becker * this is not true, the read of -1 (UINT64_MAX) will fail. 1331c8d9a6aSJoel Becker */ 1348cb471e8SJoel Becker ret = ocfs2_read_blocks(INODE_CACHE(si->si_inode), -1, si->si_blocks, 1358cb471e8SJoel Becker si->si_bh, OCFS2_BH_IGNORE_CACHE, NULL); 136d85b20e4SJoel Becker if (ret == 0) { 137d85b20e4SJoel Becker spin_lock(&osb->osb_lock); 1388e8a4603SMark Fasheh ocfs2_update_slot_info(si); 139d85b20e4SJoel Becker spin_unlock(&osb->osb_lock); 140d85b20e4SJoel Becker } 1418e8a4603SMark Fasheh 1428e8a4603SMark Fasheh return ret; 1438e8a4603SMark Fasheh } 1448e8a4603SMark Fasheh 145ccd979bdSMark Fasheh /* post the our slot info stuff into it's destination bh and write it 146ccd979bdSMark Fasheh * out. */ 147386a2ef8SJoel Becker static void ocfs2_update_disk_slot_extended(struct ocfs2_slot_info *si, 148386a2ef8SJoel Becker int slot_num, 149386a2ef8SJoel Becker struct buffer_head **bh) 150ccd979bdSMark Fasheh { 151386a2ef8SJoel Becker int blkind = slot_num / si->si_slots_per_block; 152386a2ef8SJoel Becker int slotno = slot_num % si->si_slots_per_block; 153386a2ef8SJoel Becker struct ocfs2_slot_map_extended *se; 154386a2ef8SJoel Becker 155386a2ef8SJoel Becker BUG_ON(blkind >= si->si_blocks); 156386a2ef8SJoel Becker 157386a2ef8SJoel Becker se = (struct ocfs2_slot_map_extended *)si->si_bh[blkind]->b_data; 158386a2ef8SJoel Becker se->se_slots[slotno].es_valid = si->si_slots[slot_num].sl_valid; 159386a2ef8SJoel Becker if (si->si_slots[slot_num].sl_valid) 160386a2ef8SJoel Becker se->se_slots[slotno].es_node_num = 161386a2ef8SJoel Becker cpu_to_le32(si->si_slots[slot_num].sl_node_num); 162386a2ef8SJoel Becker *bh = si->si_bh[blkind]; 163386a2ef8SJoel Becker } 164386a2ef8SJoel Becker 165386a2ef8SJoel Becker static void ocfs2_update_disk_slot_old(struct ocfs2_slot_info *si, 166386a2ef8SJoel Becker int slot_num, 167386a2ef8SJoel Becker struct buffer_head **bh) 168386a2ef8SJoel Becker { 169386a2ef8SJoel Becker int i; 170fb86b1f0SJoel Becker struct ocfs2_slot_map *sm; 171ccd979bdSMark Fasheh 172fb86b1f0SJoel Becker sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data; 173fc881fa0SJoel Becker for (i = 0; i < si->si_num_slots; i++) { 174fc881fa0SJoel Becker if (si->si_slots[i].sl_valid) 175fb86b1f0SJoel Becker sm->sm_slots[i] = 176fc881fa0SJoel Becker cpu_to_le16(si->si_slots[i].sl_node_num); 177fc881fa0SJoel Becker else 178fb86b1f0SJoel Becker sm->sm_slots[i] = cpu_to_le16(OCFS2_INVALID_SLOT); 179fc881fa0SJoel Becker } 180386a2ef8SJoel Becker *bh = si->si_bh[0]; 181386a2ef8SJoel Becker } 182386a2ef8SJoel Becker 183386a2ef8SJoel Becker static int ocfs2_update_disk_slot(struct ocfs2_super *osb, 184386a2ef8SJoel Becker struct ocfs2_slot_info *si, 185386a2ef8SJoel Becker int slot_num) 186386a2ef8SJoel Becker { 187386a2ef8SJoel Becker int status; 188386a2ef8SJoel Becker struct buffer_head *bh; 189386a2ef8SJoel Becker 190386a2ef8SJoel Becker spin_lock(&osb->osb_lock); 191386a2ef8SJoel Becker if (si->si_extended) 192386a2ef8SJoel Becker ocfs2_update_disk_slot_extended(si, slot_num, &bh); 193386a2ef8SJoel Becker else 194386a2ef8SJoel Becker ocfs2_update_disk_slot_old(si, slot_num, &bh); 195d85b20e4SJoel Becker spin_unlock(&osb->osb_lock); 196ccd979bdSMark Fasheh 1978cb471e8SJoel Becker status = ocfs2_write_block(osb, bh, INODE_CACHE(si->si_inode)); 198ccd979bdSMark Fasheh if (status < 0) 199ccd979bdSMark Fasheh mlog_errno(status); 200ccd979bdSMark Fasheh 201ccd979bdSMark Fasheh return status; 202ccd979bdSMark Fasheh } 203ccd979bdSMark Fasheh 2041c8d9a6aSJoel Becker /* 2051c8d9a6aSJoel Becker * Calculate how many bytes are needed by the slot map. Returns 2061c8d9a6aSJoel Becker * an error if the slot map file is too small. 2071c8d9a6aSJoel Becker */ 2081c8d9a6aSJoel Becker static int ocfs2_slot_map_physical_size(struct ocfs2_super *osb, 2091c8d9a6aSJoel Becker struct inode *inode, 2101c8d9a6aSJoel Becker unsigned long long *bytes) 2111c8d9a6aSJoel Becker { 2121c8d9a6aSJoel Becker unsigned long long bytes_needed; 2131c8d9a6aSJoel Becker 214386a2ef8SJoel Becker if (ocfs2_uses_extended_slot_map(osb)) { 215386a2ef8SJoel Becker bytes_needed = osb->max_slots * 216386a2ef8SJoel Becker sizeof(struct ocfs2_extended_slot); 217386a2ef8SJoel Becker } else { 2181c8d9a6aSJoel Becker bytes_needed = osb->max_slots * sizeof(__le16); 219386a2ef8SJoel Becker } 2201c8d9a6aSJoel Becker if (bytes_needed > i_size_read(inode)) { 2211c8d9a6aSJoel Becker mlog(ML_ERROR, 2221c8d9a6aSJoel Becker "Slot map file is too small! (size %llu, needed %llu)\n", 2231c8d9a6aSJoel Becker i_size_read(inode), bytes_needed); 2241c8d9a6aSJoel Becker return -ENOSPC; 2251c8d9a6aSJoel Becker } 2261c8d9a6aSJoel Becker 2271c8d9a6aSJoel Becker *bytes = bytes_needed; 2281c8d9a6aSJoel Becker return 0; 2291c8d9a6aSJoel Becker } 2301c8d9a6aSJoel Becker 231fc881fa0SJoel Becker /* try to find global node in the slot info. Returns -ENOENT 232fc881fa0SJoel Becker * if nothing is found. */ 233fc881fa0SJoel Becker static int __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si, 234fc881fa0SJoel Becker unsigned int node_num) 235ccd979bdSMark Fasheh { 236fc881fa0SJoel Becker int i, ret = -ENOENT; 237ccd979bdSMark Fasheh 238ccd979bdSMark Fasheh for(i = 0; i < si->si_num_slots; i++) { 239fc881fa0SJoel Becker if (si->si_slots[i].sl_valid && 240fc881fa0SJoel Becker (node_num == si->si_slots[i].sl_node_num)) { 241fc881fa0SJoel Becker ret = i; 242ccd979bdSMark Fasheh break; 243ccd979bdSMark Fasheh } 244ccd979bdSMark Fasheh } 245fc881fa0SJoel Becker 246ccd979bdSMark Fasheh return ret; 247ccd979bdSMark Fasheh } 248ccd979bdSMark Fasheh 249fc881fa0SJoel Becker static int __ocfs2_find_empty_slot(struct ocfs2_slot_info *si, 250fc881fa0SJoel Becker int preferred) 251ccd979bdSMark Fasheh { 252fc881fa0SJoel Becker int i, ret = -ENOSPC; 253ccd979bdSMark Fasheh 254fc881fa0SJoel Becker if ((preferred >= 0) && (preferred < si->si_num_slots)) { 255912f655dSGang He if (!si->si_slots[preferred].sl_valid || 256912f655dSGang He !si->si_slots[preferred].sl_node_num) { 257baf4661aSSunil Mushran ret = preferred; 258baf4661aSSunil Mushran goto out; 259baf4661aSSunil Mushran } 260baf4661aSSunil Mushran } 261baf4661aSSunil Mushran 262ccd979bdSMark Fasheh for(i = 0; i < si->si_num_slots; i++) { 263912f655dSGang He if (!si->si_slots[i].sl_valid || 264912f655dSGang He !si->si_slots[i].sl_node_num) { 265fc881fa0SJoel Becker ret = i; 266ccd979bdSMark Fasheh break; 267ccd979bdSMark Fasheh } 268ccd979bdSMark Fasheh } 269baf4661aSSunil Mushran out: 270ccd979bdSMark Fasheh return ret; 271ccd979bdSMark Fasheh } 272ccd979bdSMark Fasheh 273d85b20e4SJoel Becker int ocfs2_node_num_to_slot(struct ocfs2_super *osb, unsigned int node_num) 274ccd979bdSMark Fasheh { 275fc881fa0SJoel Becker int slot; 276d85b20e4SJoel Becker struct ocfs2_slot_info *si = osb->slot_info; 277ccd979bdSMark Fasheh 278d85b20e4SJoel Becker spin_lock(&osb->osb_lock); 279d85b20e4SJoel Becker slot = __ocfs2_node_num_to_slot(si, node_num); 280d85b20e4SJoel Becker spin_unlock(&osb->osb_lock); 281d85b20e4SJoel Becker 282d85b20e4SJoel Becker return slot; 283d85b20e4SJoel Becker } 284d85b20e4SJoel Becker 285d85b20e4SJoel Becker int ocfs2_slot_to_node_num_locked(struct ocfs2_super *osb, int slot_num, 286d85b20e4SJoel Becker unsigned int *node_num) 287d85b20e4SJoel Becker { 288d85b20e4SJoel Becker struct ocfs2_slot_info *si = osb->slot_info; 289d85b20e4SJoel Becker 290d85b20e4SJoel Becker assert_spin_locked(&osb->osb_lock); 291d85b20e4SJoel Becker 292d85b20e4SJoel Becker BUG_ON(slot_num < 0); 293519a2861SDan Carpenter BUG_ON(slot_num >= osb->max_slots); 294d85b20e4SJoel Becker 295fc881fa0SJoel Becker if (!si->si_slots[slot_num].sl_valid) 296d85b20e4SJoel Becker return -ENOENT; 297d85b20e4SJoel Becker 298fc881fa0SJoel Becker *node_num = si->si_slots[slot_num].sl_node_num; 299d85b20e4SJoel Becker return 0; 300ccd979bdSMark Fasheh } 301ccd979bdSMark Fasheh 3028e8a4603SMark Fasheh static void __ocfs2_free_slot_info(struct ocfs2_slot_info *si) 3038e8a4603SMark Fasheh { 3041c8d9a6aSJoel Becker unsigned int i; 3051c8d9a6aSJoel Becker 3068e8a4603SMark Fasheh if (si == NULL) 3078e8a4603SMark Fasheh return; 3088e8a4603SMark Fasheh 3098e8a4603SMark Fasheh iput(si->si_inode); 3101c8d9a6aSJoel Becker if (si->si_bh) { 3111c8d9a6aSJoel Becker for (i = 0; i < si->si_blocks; i++) { 3121c8d9a6aSJoel Becker if (si->si_bh[i]) { 3131c8d9a6aSJoel Becker brelse(si->si_bh[i]); 3141c8d9a6aSJoel Becker si->si_bh[i] = NULL; 3151c8d9a6aSJoel Becker } 3161c8d9a6aSJoel Becker } 3171c8d9a6aSJoel Becker kfree(si->si_bh); 3181c8d9a6aSJoel Becker } 3198e8a4603SMark Fasheh 3208e8a4603SMark Fasheh kfree(si); 3218e8a4603SMark Fasheh } 3228e8a4603SMark Fasheh 323fc881fa0SJoel Becker int ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num) 324ccd979bdSMark Fasheh { 3258e8a4603SMark Fasheh struct ocfs2_slot_info *si = osb->slot_info; 3268e8a4603SMark Fasheh 3278e8a4603SMark Fasheh if (si == NULL) 3288e8a4603SMark Fasheh return 0; 3298e8a4603SMark Fasheh 330d85b20e4SJoel Becker spin_lock(&osb->osb_lock); 331fc881fa0SJoel Becker ocfs2_invalidate_slot(si, slot_num); 332d85b20e4SJoel Becker spin_unlock(&osb->osb_lock); 3338e8a4603SMark Fasheh 334386a2ef8SJoel Becker return ocfs2_update_disk_slot(osb, osb->slot_info, slot_num); 335ccd979bdSMark Fasheh } 336ccd979bdSMark Fasheh 3371c8d9a6aSJoel Becker static int ocfs2_map_slot_buffers(struct ocfs2_super *osb, 3381c8d9a6aSJoel Becker struct ocfs2_slot_info *si) 3391c8d9a6aSJoel Becker { 3401c8d9a6aSJoel Becker int status = 0; 3411c8d9a6aSJoel Becker u64 blkno; 342f30d44f3SPoyo VL unsigned long long blocks, bytes = 0; 3431c8d9a6aSJoel Becker unsigned int i; 3441c8d9a6aSJoel Becker struct buffer_head *bh; 3451c8d9a6aSJoel Becker 3461c8d9a6aSJoel Becker status = ocfs2_slot_map_physical_size(osb, si->si_inode, &bytes); 3471c8d9a6aSJoel Becker if (status) 3481c8d9a6aSJoel Becker goto bail; 3491c8d9a6aSJoel Becker 3501c8d9a6aSJoel Becker blocks = ocfs2_blocks_for_bytes(si->si_inode->i_sb, bytes); 3511c8d9a6aSJoel Becker BUG_ON(blocks > UINT_MAX); 3521c8d9a6aSJoel Becker si->si_blocks = blocks; 3531c8d9a6aSJoel Becker if (!si->si_blocks) 3541c8d9a6aSJoel Becker goto bail; 3551c8d9a6aSJoel Becker 356386a2ef8SJoel Becker if (si->si_extended) 357386a2ef8SJoel Becker si->si_slots_per_block = 358386a2ef8SJoel Becker (osb->sb->s_blocksize / 359386a2ef8SJoel Becker sizeof(struct ocfs2_extended_slot)); 360386a2ef8SJoel Becker else 361386a2ef8SJoel Becker si->si_slots_per_block = osb->sb->s_blocksize / sizeof(__le16); 362386a2ef8SJoel Becker 363386a2ef8SJoel Becker /* The size checks above should ensure this */ 364386a2ef8SJoel Becker BUG_ON((osb->max_slots / si->si_slots_per_block) > blocks); 365386a2ef8SJoel Becker 366a8731086STao Ma trace_ocfs2_map_slot_buffers(bytes, si->si_blocks); 3671c8d9a6aSJoel Becker 3681b7f8ba6SFabian Frederick si->si_bh = kcalloc(si->si_blocks, sizeof(struct buffer_head *), 3691c8d9a6aSJoel Becker GFP_KERNEL); 3701c8d9a6aSJoel Becker if (!si->si_bh) { 3711c8d9a6aSJoel Becker status = -ENOMEM; 3721c8d9a6aSJoel Becker mlog_errno(status); 3731c8d9a6aSJoel Becker goto bail; 3741c8d9a6aSJoel Becker } 3751c8d9a6aSJoel Becker 3761c8d9a6aSJoel Becker for (i = 0; i < si->si_blocks; i++) { 3771c8d9a6aSJoel Becker status = ocfs2_extent_map_get_blocks(si->si_inode, i, 3781c8d9a6aSJoel Becker &blkno, NULL, NULL); 3791c8d9a6aSJoel Becker if (status < 0) { 3801c8d9a6aSJoel Becker mlog_errno(status); 3811c8d9a6aSJoel Becker goto bail; 3821c8d9a6aSJoel Becker } 3831c8d9a6aSJoel Becker 384a8731086STao Ma trace_ocfs2_map_slot_buffers_block((unsigned long long)blkno, i); 3851c8d9a6aSJoel Becker 3861c8d9a6aSJoel Becker bh = NULL; /* Acquire a fresh bh */ 3878cb471e8SJoel Becker status = ocfs2_read_blocks(INODE_CACHE(si->si_inode), blkno, 3888cb471e8SJoel Becker 1, &bh, OCFS2_BH_IGNORE_CACHE, NULL); 3891c8d9a6aSJoel Becker if (status < 0) { 3901c8d9a6aSJoel Becker mlog_errno(status); 3911c8d9a6aSJoel Becker goto bail; 3921c8d9a6aSJoel Becker } 3931c8d9a6aSJoel Becker 3941c8d9a6aSJoel Becker si->si_bh[i] = bh; 3951c8d9a6aSJoel Becker } 3961c8d9a6aSJoel Becker 3971c8d9a6aSJoel Becker bail: 3981c8d9a6aSJoel Becker return status; 3991c8d9a6aSJoel Becker } 4001c8d9a6aSJoel Becker 401ccd979bdSMark Fasheh int ocfs2_init_slot_info(struct ocfs2_super *osb) 402ccd979bdSMark Fasheh { 403fc881fa0SJoel Becker int status; 404ccd979bdSMark Fasheh struct inode *inode = NULL; 405ccd979bdSMark Fasheh struct ocfs2_slot_info *si; 406ccd979bdSMark Fasheh 407f402cf03SGustavo A. R. Silva si = kzalloc(struct_size(si, si_slots, osb->max_slots), GFP_KERNEL); 408ccd979bdSMark Fasheh if (!si) { 409ccd979bdSMark Fasheh status = -ENOMEM; 410ccd979bdSMark Fasheh mlog_errno(status); 411bb34ed21SMarkus Elfring return status; 412ccd979bdSMark Fasheh } 413ccd979bdSMark Fasheh 414386a2ef8SJoel Becker si->si_extended = ocfs2_uses_extended_slot_map(osb); 415ccd979bdSMark Fasheh si->si_num_slots = osb->max_slots; 416ccd979bdSMark Fasheh 417ccd979bdSMark Fasheh inode = ocfs2_get_system_file_inode(osb, SLOT_MAP_SYSTEM_INODE, 418ccd979bdSMark Fasheh OCFS2_INVALID_SLOT); 419ccd979bdSMark Fasheh if (!inode) { 420ccd979bdSMark Fasheh status = -EINVAL; 421ccd979bdSMark Fasheh mlog_errno(status); 422ccd979bdSMark Fasheh goto bail; 423ccd979bdSMark Fasheh } 424ccd979bdSMark Fasheh 425ccd979bdSMark Fasheh si->si_inode = inode; 4261c8d9a6aSJoel Becker status = ocfs2_map_slot_buffers(osb, si); 4271c8d9a6aSJoel Becker if (status < 0) { 4281c8d9a6aSJoel Becker mlog_errno(status); 4291c8d9a6aSJoel Becker goto bail; 4301c8d9a6aSJoel Becker } 4311c8d9a6aSJoel Becker 432d85b20e4SJoel Becker osb->slot_info = (struct ocfs2_slot_info *)si; 433ccd979bdSMark Fasheh bail: 434fd90d4dfSMarkus Elfring if (status < 0) 4358e8a4603SMark Fasheh __ocfs2_free_slot_info(si); 436ccd979bdSMark Fasheh 437ccd979bdSMark Fasheh return status; 438ccd979bdSMark Fasheh } 439ccd979bdSMark Fasheh 4408e8a4603SMark Fasheh void ocfs2_free_slot_info(struct ocfs2_super *osb) 441ccd979bdSMark Fasheh { 4428e8a4603SMark Fasheh struct ocfs2_slot_info *si = osb->slot_info; 4438e8a4603SMark Fasheh 4448e8a4603SMark Fasheh osb->slot_info = NULL; 4458e8a4603SMark Fasheh __ocfs2_free_slot_info(si); 446ccd979bdSMark Fasheh } 447ccd979bdSMark Fasheh 448ccd979bdSMark Fasheh int ocfs2_find_slot(struct ocfs2_super *osb) 449ccd979bdSMark Fasheh { 450ccd979bdSMark Fasheh int status; 451fc881fa0SJoel Becker int slot; 452ccd979bdSMark Fasheh struct ocfs2_slot_info *si; 453ccd979bdSMark Fasheh 454ccd979bdSMark Fasheh si = osb->slot_info; 455ccd979bdSMark Fasheh 456d85b20e4SJoel Becker spin_lock(&osb->osb_lock); 457ccd979bdSMark Fasheh ocfs2_update_slot_info(si); 458ccd979bdSMark Fasheh 459912f655dSGang He if (ocfs2_mount_local(osb)) 460912f655dSGang He /* use slot 0 directly in local mode */ 461912f655dSGang He slot = 0; 462912f655dSGang He else { 463ccd979bdSMark Fasheh /* search for ourselves first and take the slot if it already 464ccd979bdSMark Fasheh * exists. Perhaps we need to mark this in a variable for our 465ccd979bdSMark Fasheh * own journal recovery? Possibly not, though we certainly 466ccd979bdSMark Fasheh * need to warn to the user */ 467ccd979bdSMark Fasheh slot = __ocfs2_node_num_to_slot(si, osb->node_num); 468fc881fa0SJoel Becker if (slot < 0) { 469ccd979bdSMark Fasheh /* if no slot yet, then just take 1st available 470ccd979bdSMark Fasheh * one. */ 471baf4661aSSunil Mushran slot = __ocfs2_find_empty_slot(si, osb->preferred_slot); 472fc881fa0SJoel Becker if (slot < 0) { 473d85b20e4SJoel Becker spin_unlock(&osb->osb_lock); 474ccd979bdSMark Fasheh mlog(ML_ERROR, "no free slots available!\n"); 475ccd979bdSMark Fasheh status = -EINVAL; 476ccd979bdSMark Fasheh goto bail; 477ccd979bdSMark Fasheh } 478ccd979bdSMark Fasheh } else 479912f655dSGang He printk(KERN_INFO "ocfs2: Slot %d on device (%s) was " 480912f655dSGang He "already allocated to this node!\n", 481912f655dSGang He slot, osb->dev_str); 482912f655dSGang He } 483ccd979bdSMark Fasheh 484fc881fa0SJoel Becker ocfs2_set_slot(si, slot, osb->node_num); 485ccd979bdSMark Fasheh osb->slot_num = slot; 486d85b20e4SJoel Becker spin_unlock(&osb->osb_lock); 487ccd979bdSMark Fasheh 488a8731086STao Ma trace_ocfs2_find_slot(osb->slot_num); 489ccd979bdSMark Fasheh 490386a2ef8SJoel Becker status = ocfs2_update_disk_slot(osb, si, osb->slot_num); 4911247017fSjiangyiwen if (status < 0) { 492ccd979bdSMark Fasheh mlog_errno(status); 4931247017fSjiangyiwen /* 4941247017fSjiangyiwen * if write block failed, invalidate slot to avoid overwrite 4951247017fSjiangyiwen * slot during dismount in case another node rightly has mounted 4961247017fSjiangyiwen */ 4971247017fSjiangyiwen spin_lock(&osb->osb_lock); 4981247017fSjiangyiwen ocfs2_invalidate_slot(si, osb->slot_num); 4991247017fSjiangyiwen osb->slot_num = OCFS2_INVALID_SLOT; 5001247017fSjiangyiwen spin_unlock(&osb->osb_lock); 5011247017fSjiangyiwen } 502ccd979bdSMark Fasheh 503ccd979bdSMark Fasheh bail: 504ccd979bdSMark Fasheh return status; 505ccd979bdSMark Fasheh } 506ccd979bdSMark Fasheh 507ccd979bdSMark Fasheh void ocfs2_put_slot(struct ocfs2_super *osb) 508ccd979bdSMark Fasheh { 509386a2ef8SJoel Becker int status, slot_num; 510ccd979bdSMark Fasheh struct ocfs2_slot_info *si = osb->slot_info; 511ccd979bdSMark Fasheh 512ccd979bdSMark Fasheh if (!si) 513ccd979bdSMark Fasheh return; 514ccd979bdSMark Fasheh 515d85b20e4SJoel Becker spin_lock(&osb->osb_lock); 516ccd979bdSMark Fasheh ocfs2_update_slot_info(si); 517ccd979bdSMark Fasheh 518386a2ef8SJoel Becker slot_num = osb->slot_num; 519fc881fa0SJoel Becker ocfs2_invalidate_slot(si, osb->slot_num); 520ccd979bdSMark Fasheh osb->slot_num = OCFS2_INVALID_SLOT; 521d85b20e4SJoel Becker spin_unlock(&osb->osb_lock); 522ccd979bdSMark Fasheh 523386a2ef8SJoel Becker status = ocfs2_update_disk_slot(osb, si, slot_num); 5248f9b1802SGuozhonghua if (status < 0) 525ccd979bdSMark Fasheh mlog_errno(status); 526ccd979bdSMark Fasheh 5278e8a4603SMark Fasheh ocfs2_free_slot_info(osb); 528ccd979bdSMark Fasheh } 529