xref: /openbmc/linux/fs/ocfs2/slot_map.c (revision fc881fa0d59596c02f8707b5572567c369d4789a)
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 
45*fc881fa0SJoel Becker 
46*fc881fa0SJoel Becker struct ocfs2_slot {
47*fc881fa0SJoel Becker 	int sl_valid;
48*fc881fa0SJoel Becker 	unsigned int sl_node_num;
49*fc881fa0SJoel Becker };
50*fc881fa0SJoel Becker 
51d85b20e4SJoel Becker struct ocfs2_slot_info {
52d85b20e4SJoel Becker 	struct inode *si_inode;
531c8d9a6aSJoel Becker 	unsigned int si_blocks;
541c8d9a6aSJoel Becker 	struct buffer_head **si_bh;
55d85b20e4SJoel Becker 	unsigned int si_num_slots;
56*fc881fa0SJoel Becker 	struct ocfs2_slot *si_slots;
57d85b20e4SJoel Becker };
58d85b20e4SJoel Becker 
59d85b20e4SJoel Becker 
60*fc881fa0SJoel Becker static int __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
61*fc881fa0SJoel Becker 				    unsigned int node_num);
62*fc881fa0SJoel Becker 
63*fc881fa0SJoel Becker static void ocfs2_invalidate_slot(struct ocfs2_slot_info *si,
64*fc881fa0SJoel Becker 				  int slot_num)
65*fc881fa0SJoel Becker {
66*fc881fa0SJoel Becker 	BUG_ON((slot_num < 0) || (slot_num >= si->si_num_slots));
67*fc881fa0SJoel Becker 	si->si_slots[slot_num].sl_valid = 0;
68*fc881fa0SJoel Becker }
69*fc881fa0SJoel Becker 
70*fc881fa0SJoel Becker static void ocfs2_set_slot(struct ocfs2_slot_info *si,
71*fc881fa0SJoel Becker 			   int slot_num, unsigned int node_num)
72*fc881fa0SJoel Becker {
73*fc881fa0SJoel Becker 	BUG_ON((slot_num < 0) || (slot_num >= si->si_num_slots));
74*fc881fa0SJoel Becker 	BUG_ON((node_num == O2NM_INVALID_NODE_NUM) ||
75*fc881fa0SJoel Becker 	       (node_num >= O2NM_MAX_NODES));
76*fc881fa0SJoel Becker 
77*fc881fa0SJoel Becker 	si->si_slots[slot_num].sl_valid = 1;
78*fc881fa0SJoel Becker 	si->si_slots[slot_num].sl_node_num = node_num;
79*fc881fa0SJoel Becker }
80ccd979bdSMark Fasheh 
81d85b20e4SJoel Becker /*
82d85b20e4SJoel Becker  * Post the slot information on disk into our slot_info struct.
83d85b20e4SJoel Becker  * Must be protected by osb_lock.
84d85b20e4SJoel Becker  */
858e8a4603SMark Fasheh static void ocfs2_update_slot_info(struct ocfs2_slot_info *si)
86ccd979bdSMark Fasheh {
87ccd979bdSMark Fasheh 	int i;
88ccd979bdSMark Fasheh 	__le16 *disk_info;
89ccd979bdSMark Fasheh 
90ccd979bdSMark Fasheh 	/* we don't read the slot block here as ocfs2_super_lock
91ccd979bdSMark Fasheh 	 * should've made sure we have the most recent copy. */
921c8d9a6aSJoel Becker 	disk_info = (__le16 *) si->si_bh[0]->b_data;
93ccd979bdSMark Fasheh 
94*fc881fa0SJoel Becker 	for (i = 0; i < si->si_num_slots; i++) {
95*fc881fa0SJoel Becker 		if (le16_to_cpu(disk_info[i]) == (u16)OCFS2_INVALID_SLOT)
96*fc881fa0SJoel Becker 			ocfs2_invalidate_slot(si, i);
97*fc881fa0SJoel Becker 		else
98*fc881fa0SJoel Becker 			ocfs2_set_slot(si, i, le16_to_cpu(disk_info[i]));
99*fc881fa0SJoel Becker 	}
100ccd979bdSMark Fasheh }
101ccd979bdSMark Fasheh 
1028e8a4603SMark Fasheh int ocfs2_refresh_slot_info(struct ocfs2_super *osb)
1038e8a4603SMark Fasheh {
1048e8a4603SMark Fasheh 	int ret;
1058e8a4603SMark Fasheh 	struct ocfs2_slot_info *si = osb->slot_info;
1068e8a4603SMark Fasheh 
1078e8a4603SMark Fasheh 	if (si == NULL)
1088e8a4603SMark Fasheh 		return 0;
1098e8a4603SMark Fasheh 
1101c8d9a6aSJoel Becker 	BUG_ON(si->si_blocks == 0);
1111c8d9a6aSJoel Becker 	BUG_ON(si->si_bh == NULL);
1121c8d9a6aSJoel Becker 
1131c8d9a6aSJoel Becker 	mlog(0, "Refreshing slot map, reading %u block(s)\n",
1141c8d9a6aSJoel Becker 	     si->si_blocks);
1151c8d9a6aSJoel Becker 
1161c8d9a6aSJoel Becker 	/*
1171c8d9a6aSJoel Becker 	 * We pass -1 as blocknr because we expect all of si->si_bh to
1181c8d9a6aSJoel Becker 	 * be !NULL.  Thus, ocfs2_read_blocks() will ignore blocknr.  If
1191c8d9a6aSJoel Becker 	 * this is not true, the read of -1 (UINT64_MAX) will fail.
1201c8d9a6aSJoel Becker 	 */
1211c8d9a6aSJoel Becker 	ret = ocfs2_read_blocks(osb, -1, si->si_blocks, si->si_bh, 0,
1221c8d9a6aSJoel Becker 				si->si_inode);
123d85b20e4SJoel Becker 	if (ret == 0) {
124d85b20e4SJoel Becker 		spin_lock(&osb->osb_lock);
1258e8a4603SMark Fasheh 		ocfs2_update_slot_info(si);
126d85b20e4SJoel Becker 		spin_unlock(&osb->osb_lock);
127d85b20e4SJoel Becker 	}
1288e8a4603SMark Fasheh 
1298e8a4603SMark Fasheh 	return ret;
1308e8a4603SMark Fasheh }
1318e8a4603SMark Fasheh 
132ccd979bdSMark Fasheh /* post the our slot info stuff into it's destination bh and write it
133ccd979bdSMark Fasheh  * out. */
1348e8a4603SMark Fasheh static int ocfs2_update_disk_slots(struct ocfs2_super *osb,
135ccd979bdSMark Fasheh 				   struct ocfs2_slot_info *si)
136ccd979bdSMark Fasheh {
137ccd979bdSMark Fasheh 	int status, i;
1381c8d9a6aSJoel Becker 	__le16 *disk_info = (__le16 *) si->si_bh[0]->b_data;
139ccd979bdSMark Fasheh 
140d85b20e4SJoel Becker 	spin_lock(&osb->osb_lock);
141*fc881fa0SJoel Becker 	for (i = 0; i < si->si_num_slots; i++) {
142*fc881fa0SJoel Becker 		if (si->si_slots[i].sl_valid)
143*fc881fa0SJoel Becker 			disk_info[i] =
144*fc881fa0SJoel Becker 				cpu_to_le16(si->si_slots[i].sl_node_num);
145*fc881fa0SJoel Becker 		else
146*fc881fa0SJoel Becker 			disk_info[i] = cpu_to_le16(OCFS2_INVALID_SLOT);
147*fc881fa0SJoel Becker 	}
148d85b20e4SJoel Becker 	spin_unlock(&osb->osb_lock);
149ccd979bdSMark Fasheh 
1501c8d9a6aSJoel Becker 	status = ocfs2_write_block(osb, si->si_bh[0], si->si_inode);
151ccd979bdSMark Fasheh 	if (status < 0)
152ccd979bdSMark Fasheh 		mlog_errno(status);
153ccd979bdSMark Fasheh 
154ccd979bdSMark Fasheh 	return status;
155ccd979bdSMark Fasheh }
156ccd979bdSMark Fasheh 
1571c8d9a6aSJoel Becker /*
1581c8d9a6aSJoel Becker  * Calculate how many bytes are needed by the slot map.  Returns
1591c8d9a6aSJoel Becker  * an error if the slot map file is too small.
1601c8d9a6aSJoel Becker  */
1611c8d9a6aSJoel Becker static int ocfs2_slot_map_physical_size(struct ocfs2_super *osb,
1621c8d9a6aSJoel Becker 					struct inode *inode,
1631c8d9a6aSJoel Becker 					unsigned long long *bytes)
1641c8d9a6aSJoel Becker {
1651c8d9a6aSJoel Becker 	unsigned long long bytes_needed;
1661c8d9a6aSJoel Becker 
1671c8d9a6aSJoel Becker 	bytes_needed = osb->max_slots * sizeof(__le16);
1681c8d9a6aSJoel Becker 	if (bytes_needed > i_size_read(inode)) {
1691c8d9a6aSJoel Becker 		mlog(ML_ERROR,
1701c8d9a6aSJoel Becker 		     "Slot map file is too small!  (size %llu, needed %llu)\n",
1711c8d9a6aSJoel Becker 		     i_size_read(inode), bytes_needed);
1721c8d9a6aSJoel Becker 		return -ENOSPC;
1731c8d9a6aSJoel Becker 	}
1741c8d9a6aSJoel Becker 
1751c8d9a6aSJoel Becker 	*bytes = bytes_needed;
1761c8d9a6aSJoel Becker 	return 0;
1771c8d9a6aSJoel Becker }
1781c8d9a6aSJoel Becker 
179*fc881fa0SJoel Becker /* try to find global node in the slot info. Returns -ENOENT
180*fc881fa0SJoel Becker  * if nothing is found. */
181*fc881fa0SJoel Becker static int __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
182*fc881fa0SJoel Becker 				    unsigned int node_num)
183ccd979bdSMark Fasheh {
184*fc881fa0SJoel Becker 	int i, ret = -ENOENT;
185ccd979bdSMark Fasheh 
186ccd979bdSMark Fasheh 	for(i = 0; i < si->si_num_slots; i++) {
187*fc881fa0SJoel Becker 		if (si->si_slots[i].sl_valid &&
188*fc881fa0SJoel Becker 		    (node_num == si->si_slots[i].sl_node_num)) {
189*fc881fa0SJoel Becker 			ret = i;
190ccd979bdSMark Fasheh 			break;
191ccd979bdSMark Fasheh 		}
192ccd979bdSMark Fasheh 	}
193*fc881fa0SJoel Becker 
194ccd979bdSMark Fasheh 	return ret;
195ccd979bdSMark Fasheh }
196ccd979bdSMark Fasheh 
197*fc881fa0SJoel Becker static int __ocfs2_find_empty_slot(struct ocfs2_slot_info *si,
198*fc881fa0SJoel Becker 				   int preferred)
199ccd979bdSMark Fasheh {
200*fc881fa0SJoel Becker 	int i, ret = -ENOSPC;
201ccd979bdSMark Fasheh 
202*fc881fa0SJoel Becker 	if ((preferred >= 0) && (preferred < si->si_num_slots)) {
203*fc881fa0SJoel Becker 		if (!si->si_slots[preferred].sl_valid) {
204baf4661aSSunil Mushran 			ret = preferred;
205baf4661aSSunil Mushran 			goto out;
206baf4661aSSunil Mushran 		}
207baf4661aSSunil Mushran 	}
208baf4661aSSunil Mushran 
209ccd979bdSMark Fasheh 	for(i = 0; i < si->si_num_slots; i++) {
210*fc881fa0SJoel Becker 		if (!si->si_slots[i].sl_valid) {
211*fc881fa0SJoel Becker 			ret = i;
212ccd979bdSMark Fasheh 			break;
213ccd979bdSMark Fasheh 		}
214ccd979bdSMark Fasheh 	}
215baf4661aSSunil Mushran out:
216ccd979bdSMark Fasheh 	return ret;
217ccd979bdSMark Fasheh }
218ccd979bdSMark Fasheh 
219d85b20e4SJoel Becker int ocfs2_node_num_to_slot(struct ocfs2_super *osb, unsigned int node_num)
220ccd979bdSMark Fasheh {
221*fc881fa0SJoel Becker 	int slot;
222d85b20e4SJoel Becker 	struct ocfs2_slot_info *si = osb->slot_info;
223ccd979bdSMark Fasheh 
224d85b20e4SJoel Becker 	spin_lock(&osb->osb_lock);
225d85b20e4SJoel Becker 	slot = __ocfs2_node_num_to_slot(si, node_num);
226d85b20e4SJoel Becker 	spin_unlock(&osb->osb_lock);
227d85b20e4SJoel Becker 
228d85b20e4SJoel Becker 	return slot;
229d85b20e4SJoel Becker }
230d85b20e4SJoel Becker 
231d85b20e4SJoel Becker int ocfs2_slot_to_node_num_locked(struct ocfs2_super *osb, int slot_num,
232d85b20e4SJoel Becker 				  unsigned int *node_num)
233d85b20e4SJoel Becker {
234d85b20e4SJoel Becker 	struct ocfs2_slot_info *si = osb->slot_info;
235d85b20e4SJoel Becker 
236d85b20e4SJoel Becker 	assert_spin_locked(&osb->osb_lock);
237d85b20e4SJoel Becker 
238d85b20e4SJoel Becker 	BUG_ON(slot_num < 0);
239d85b20e4SJoel Becker 	BUG_ON(slot_num > osb->max_slots);
240d85b20e4SJoel Becker 
241*fc881fa0SJoel Becker 	if (!si->si_slots[slot_num].sl_valid)
242d85b20e4SJoel Becker 		return -ENOENT;
243d85b20e4SJoel Becker 
244*fc881fa0SJoel Becker 	*node_num = si->si_slots[slot_num].sl_node_num;
245d85b20e4SJoel Becker 	return 0;
246ccd979bdSMark Fasheh }
247ccd979bdSMark Fasheh 
2488e8a4603SMark Fasheh static void __ocfs2_free_slot_info(struct ocfs2_slot_info *si)
2498e8a4603SMark Fasheh {
2501c8d9a6aSJoel Becker 	unsigned int i;
2511c8d9a6aSJoel Becker 
2528e8a4603SMark Fasheh 	if (si == NULL)
2538e8a4603SMark Fasheh 		return;
2548e8a4603SMark Fasheh 
2558e8a4603SMark Fasheh 	if (si->si_inode)
2568e8a4603SMark Fasheh 		iput(si->si_inode);
2571c8d9a6aSJoel Becker 	if (si->si_bh) {
2581c8d9a6aSJoel Becker 		for (i = 0; i < si->si_blocks; i++) {
2591c8d9a6aSJoel Becker 			if (si->si_bh[i]) {
2601c8d9a6aSJoel Becker 				brelse(si->si_bh[i]);
2611c8d9a6aSJoel Becker 				si->si_bh[i] = NULL;
2621c8d9a6aSJoel Becker 			}
2631c8d9a6aSJoel Becker 		}
2641c8d9a6aSJoel Becker 		kfree(si->si_bh);
2651c8d9a6aSJoel Becker 	}
2668e8a4603SMark Fasheh 
2678e8a4603SMark Fasheh 	kfree(si);
2688e8a4603SMark Fasheh }
2698e8a4603SMark Fasheh 
270*fc881fa0SJoel Becker int ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num)
271ccd979bdSMark Fasheh {
2728e8a4603SMark Fasheh 	struct ocfs2_slot_info *si = osb->slot_info;
2738e8a4603SMark Fasheh 
2748e8a4603SMark Fasheh 	if (si == NULL)
2758e8a4603SMark Fasheh 		return 0;
2768e8a4603SMark Fasheh 
277d85b20e4SJoel Becker 	spin_lock(&osb->osb_lock);
278*fc881fa0SJoel Becker 	ocfs2_invalidate_slot(si, slot_num);
279d85b20e4SJoel Becker 	spin_unlock(&osb->osb_lock);
2808e8a4603SMark Fasheh 
2818e8a4603SMark Fasheh 	return ocfs2_update_disk_slots(osb, osb->slot_info);
282ccd979bdSMark Fasheh }
283ccd979bdSMark Fasheh 
2841c8d9a6aSJoel Becker static int ocfs2_map_slot_buffers(struct ocfs2_super *osb,
2851c8d9a6aSJoel Becker 				  struct ocfs2_slot_info *si)
2861c8d9a6aSJoel Becker {
2871c8d9a6aSJoel Becker 	int status = 0;
2881c8d9a6aSJoel Becker 	u64 blkno;
2891c8d9a6aSJoel Becker 	unsigned long long blocks, bytes;
2901c8d9a6aSJoel Becker 	unsigned int i;
2911c8d9a6aSJoel Becker 	struct buffer_head *bh;
2921c8d9a6aSJoel Becker 
2931c8d9a6aSJoel Becker 	status = ocfs2_slot_map_physical_size(osb, si->si_inode, &bytes);
2941c8d9a6aSJoel Becker 	if (status)
2951c8d9a6aSJoel Becker 		goto bail;
2961c8d9a6aSJoel Becker 
2971c8d9a6aSJoel Becker 	blocks = ocfs2_blocks_for_bytes(si->si_inode->i_sb, bytes);
2981c8d9a6aSJoel Becker 	BUG_ON(blocks > UINT_MAX);
2991c8d9a6aSJoel Becker 	si->si_blocks = blocks;
3001c8d9a6aSJoel Becker 	if (!si->si_blocks)
3011c8d9a6aSJoel Becker 		goto bail;
3021c8d9a6aSJoel Becker 
3031c8d9a6aSJoel Becker 	mlog(0, "Slot map needs %u buffers for %llu bytes\n",
3041c8d9a6aSJoel Becker 	     si->si_blocks, bytes);
3051c8d9a6aSJoel Becker 
3061c8d9a6aSJoel Becker 	si->si_bh = kzalloc(sizeof(struct buffer_head *) * si->si_blocks,
3071c8d9a6aSJoel Becker 			    GFP_KERNEL);
3081c8d9a6aSJoel Becker 	if (!si->si_bh) {
3091c8d9a6aSJoel Becker 		status = -ENOMEM;
3101c8d9a6aSJoel Becker 		mlog_errno(status);
3111c8d9a6aSJoel Becker 		goto bail;
3121c8d9a6aSJoel Becker 	}
3131c8d9a6aSJoel Becker 
3141c8d9a6aSJoel Becker 	for (i = 0; i < si->si_blocks; i++) {
3151c8d9a6aSJoel Becker 		status = ocfs2_extent_map_get_blocks(si->si_inode, i,
3161c8d9a6aSJoel Becker 						     &blkno, NULL, NULL);
3171c8d9a6aSJoel Becker 		if (status < 0) {
3181c8d9a6aSJoel Becker 			mlog_errno(status);
3191c8d9a6aSJoel Becker 			goto bail;
3201c8d9a6aSJoel Becker 		}
3211c8d9a6aSJoel Becker 
3221c8d9a6aSJoel Becker 		mlog(0, "Reading slot map block %u at %llu\n", i,
3231c8d9a6aSJoel Becker 		     (unsigned long long)blkno);
3241c8d9a6aSJoel Becker 
3251c8d9a6aSJoel Becker 		bh = NULL;  /* Acquire a fresh bh */
3261c8d9a6aSJoel Becker 		status = ocfs2_read_block(osb, blkno, &bh, 0, si->si_inode);
3271c8d9a6aSJoel Becker 		if (status < 0) {
3281c8d9a6aSJoel Becker 			mlog_errno(status);
3291c8d9a6aSJoel Becker 			goto bail;
3301c8d9a6aSJoel Becker 		}
3311c8d9a6aSJoel Becker 
3321c8d9a6aSJoel Becker 		si->si_bh[i] = bh;
3331c8d9a6aSJoel Becker 	}
3341c8d9a6aSJoel Becker 
3351c8d9a6aSJoel Becker bail:
3361c8d9a6aSJoel Becker 	return status;
3371c8d9a6aSJoel Becker }
3381c8d9a6aSJoel Becker 
339ccd979bdSMark Fasheh int ocfs2_init_slot_info(struct ocfs2_super *osb)
340ccd979bdSMark Fasheh {
341*fc881fa0SJoel Becker 	int status;
342ccd979bdSMark Fasheh 	struct inode *inode = NULL;
343ccd979bdSMark Fasheh 	struct ocfs2_slot_info *si;
344ccd979bdSMark Fasheh 
345*fc881fa0SJoel Becker 	si = kzalloc(sizeof(struct ocfs2_slot_info) +
346*fc881fa0SJoel Becker 		     (sizeof(struct ocfs2_slot) * osb->max_slots),
347*fc881fa0SJoel Becker 		     GFP_KERNEL);
348ccd979bdSMark Fasheh 	if (!si) {
349ccd979bdSMark Fasheh 		status = -ENOMEM;
350ccd979bdSMark Fasheh 		mlog_errno(status);
351ccd979bdSMark Fasheh 		goto bail;
352ccd979bdSMark Fasheh 	}
353ccd979bdSMark Fasheh 
354ccd979bdSMark Fasheh 	si->si_num_slots = osb->max_slots;
355*fc881fa0SJoel Becker 	si->si_slots = (struct ocfs2_slot *)((char *)si +
356*fc881fa0SJoel Becker 					     sizeof(struct ocfs2_slot_info));
357ccd979bdSMark Fasheh 
358ccd979bdSMark Fasheh 	inode = ocfs2_get_system_file_inode(osb, SLOT_MAP_SYSTEM_INODE,
359ccd979bdSMark Fasheh 					    OCFS2_INVALID_SLOT);
360ccd979bdSMark Fasheh 	if (!inode) {
361ccd979bdSMark Fasheh 		status = -EINVAL;
362ccd979bdSMark Fasheh 		mlog_errno(status);
363ccd979bdSMark Fasheh 		goto bail;
364ccd979bdSMark Fasheh 	}
365ccd979bdSMark Fasheh 
366ccd979bdSMark Fasheh 	si->si_inode = inode;
3671c8d9a6aSJoel Becker 	status = ocfs2_map_slot_buffers(osb, si);
3681c8d9a6aSJoel Becker 	if (status < 0) {
3691c8d9a6aSJoel Becker 		mlog_errno(status);
3701c8d9a6aSJoel Becker 		goto bail;
3711c8d9a6aSJoel Becker 	}
3721c8d9a6aSJoel Becker 
373d85b20e4SJoel Becker 	osb->slot_info = (struct ocfs2_slot_info *)si;
374ccd979bdSMark Fasheh bail:
375ccd979bdSMark Fasheh 	if (status < 0 && si)
3768e8a4603SMark Fasheh 		__ocfs2_free_slot_info(si);
377ccd979bdSMark Fasheh 
378ccd979bdSMark Fasheh 	return status;
379ccd979bdSMark Fasheh }
380ccd979bdSMark Fasheh 
3818e8a4603SMark Fasheh void ocfs2_free_slot_info(struct ocfs2_super *osb)
382ccd979bdSMark Fasheh {
3838e8a4603SMark Fasheh 	struct ocfs2_slot_info *si = osb->slot_info;
3848e8a4603SMark Fasheh 
3858e8a4603SMark Fasheh 	osb->slot_info = NULL;
3868e8a4603SMark Fasheh 	__ocfs2_free_slot_info(si);
387ccd979bdSMark Fasheh }
388ccd979bdSMark Fasheh 
389ccd979bdSMark Fasheh int ocfs2_find_slot(struct ocfs2_super *osb)
390ccd979bdSMark Fasheh {
391ccd979bdSMark Fasheh 	int status;
392*fc881fa0SJoel Becker 	int slot;
393ccd979bdSMark Fasheh 	struct ocfs2_slot_info *si;
394ccd979bdSMark Fasheh 
395ccd979bdSMark Fasheh 	mlog_entry_void();
396ccd979bdSMark Fasheh 
397ccd979bdSMark Fasheh 	si = osb->slot_info;
398ccd979bdSMark Fasheh 
399d85b20e4SJoel Becker 	spin_lock(&osb->osb_lock);
400ccd979bdSMark Fasheh 	ocfs2_update_slot_info(si);
401ccd979bdSMark Fasheh 
402ccd979bdSMark Fasheh 	/* search for ourselves first and take the slot if it already
403ccd979bdSMark Fasheh 	 * exists. Perhaps we need to mark this in a variable for our
404ccd979bdSMark Fasheh 	 * own journal recovery? Possibly not, though we certainly
405ccd979bdSMark Fasheh 	 * need to warn to the user */
406ccd979bdSMark Fasheh 	slot = __ocfs2_node_num_to_slot(si, osb->node_num);
407*fc881fa0SJoel Becker 	if (slot < 0) {
408ccd979bdSMark Fasheh 		/* if no slot yet, then just take 1st available
409ccd979bdSMark Fasheh 		 * one. */
410baf4661aSSunil Mushran 		slot = __ocfs2_find_empty_slot(si, osb->preferred_slot);
411*fc881fa0SJoel Becker 		if (slot < 0) {
412d85b20e4SJoel Becker 			spin_unlock(&osb->osb_lock);
413ccd979bdSMark Fasheh 			mlog(ML_ERROR, "no free slots available!\n");
414ccd979bdSMark Fasheh 			status = -EINVAL;
415ccd979bdSMark Fasheh 			goto bail;
416ccd979bdSMark Fasheh 		}
417ccd979bdSMark Fasheh 	} else
418ccd979bdSMark Fasheh 		mlog(ML_NOTICE, "slot %d is already allocated to this node!\n",
419ccd979bdSMark Fasheh 		     slot);
420ccd979bdSMark Fasheh 
421*fc881fa0SJoel Becker 	ocfs2_set_slot(si, slot, osb->node_num);
422ccd979bdSMark Fasheh 	osb->slot_num = slot;
423d85b20e4SJoel Becker 	spin_unlock(&osb->osb_lock);
424ccd979bdSMark Fasheh 
425e7607ab3SMark Fasheh 	mlog(0, "taking node slot %d\n", osb->slot_num);
426ccd979bdSMark Fasheh 
427ccd979bdSMark Fasheh 	status = ocfs2_update_disk_slots(osb, si);
428ccd979bdSMark Fasheh 	if (status < 0)
429ccd979bdSMark Fasheh 		mlog_errno(status);
430ccd979bdSMark Fasheh 
431ccd979bdSMark Fasheh bail:
432ccd979bdSMark Fasheh 	mlog_exit(status);
433ccd979bdSMark Fasheh 	return status;
434ccd979bdSMark Fasheh }
435ccd979bdSMark Fasheh 
436ccd979bdSMark Fasheh void ocfs2_put_slot(struct ocfs2_super *osb)
437ccd979bdSMark Fasheh {
438ccd979bdSMark Fasheh 	int status;
439ccd979bdSMark Fasheh 	struct ocfs2_slot_info *si = osb->slot_info;
440ccd979bdSMark Fasheh 
441ccd979bdSMark Fasheh 	if (!si)
442ccd979bdSMark Fasheh 		return;
443ccd979bdSMark Fasheh 
444d85b20e4SJoel Becker 	spin_lock(&osb->osb_lock);
445ccd979bdSMark Fasheh 	ocfs2_update_slot_info(si);
446ccd979bdSMark Fasheh 
447*fc881fa0SJoel Becker 	ocfs2_invalidate_slot(si, osb->slot_num);
448ccd979bdSMark Fasheh 	osb->slot_num = OCFS2_INVALID_SLOT;
449d85b20e4SJoel Becker 	spin_unlock(&osb->osb_lock);
450ccd979bdSMark Fasheh 
451ccd979bdSMark Fasheh 	status = ocfs2_update_disk_slots(osb, si);
452ccd979bdSMark Fasheh 	if (status < 0) {
453ccd979bdSMark Fasheh 		mlog_errno(status);
454ccd979bdSMark Fasheh 		goto bail;
455ccd979bdSMark Fasheh 	}
456ccd979bdSMark Fasheh 
457ccd979bdSMark Fasheh bail:
4588e8a4603SMark Fasheh 	ocfs2_free_slot_info(osb);
459ccd979bdSMark Fasheh }
460ccd979bdSMark Fasheh 
461