xref: /linux/fs/ocfs2/slot_map.c (revision 0ea5c948cb64bab5bc7a5516774eb8536f05aa0d)
1328970deSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2fa60ce2cSMasahiro 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;
40*e91673b8SKees Cook 	struct ocfs2_slot si_slots[] __counted_by(si_num_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 
ocfs2_invalidate_slot(struct ocfs2_slot_info * si,int slot_num)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 
ocfs2_set_slot(struct ocfs2_slot_info * si,int slot_num,unsigned int node_num)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 */
ocfs2_update_slot_info_extended(struct ocfs2_slot_info * si)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  */
ocfs2_update_slot_info_old(struct ocfs2_slot_info * si)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 
ocfs2_update_slot_info(struct ocfs2_slot_info * si)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 
ocfs2_refresh_slot_info(struct ocfs2_super * osb)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. */
ocfs2_update_disk_slot_extended(struct ocfs2_slot_info * si,int slot_num,struct buffer_head ** bh)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 
ocfs2_update_disk_slot_old(struct ocfs2_slot_info * si,int slot_num,struct buffer_head ** bh)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 
ocfs2_update_disk_slot(struct ocfs2_super * osb,struct ocfs2_slot_info * si,int slot_num)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  */
ocfs2_slot_map_physical_size(struct ocfs2_super * osb,struct inode * inode,unsigned long long * bytes)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. */
__ocfs2_node_num_to_slot(struct ocfs2_slot_info * si,unsigned int node_num)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 
__ocfs2_find_empty_slot(struct ocfs2_slot_info * si,int preferred)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)) {
255c80af0c2SJunxiao Bi 		if (!si->si_slots[preferred].sl_valid) {
256baf4661aSSunil Mushran 			ret = preferred;
257baf4661aSSunil Mushran 			goto out;
258baf4661aSSunil Mushran 		}
259baf4661aSSunil Mushran 	}
260baf4661aSSunil Mushran 
261ccd979bdSMark Fasheh 	for(i = 0; i < si->si_num_slots; i++) {
262c80af0c2SJunxiao Bi 		if (!si->si_slots[i].sl_valid) {
263fc881fa0SJoel Becker 			ret = i;
264ccd979bdSMark Fasheh 			break;
265ccd979bdSMark Fasheh 		}
266ccd979bdSMark Fasheh 	}
267baf4661aSSunil Mushran out:
268ccd979bdSMark Fasheh 	return ret;
269ccd979bdSMark Fasheh }
270ccd979bdSMark Fasheh 
ocfs2_node_num_to_slot(struct ocfs2_super * osb,unsigned int node_num)271d85b20e4SJoel Becker int ocfs2_node_num_to_slot(struct ocfs2_super *osb, unsigned int node_num)
272ccd979bdSMark Fasheh {
273fc881fa0SJoel Becker 	int slot;
274d85b20e4SJoel Becker 	struct ocfs2_slot_info *si = osb->slot_info;
275ccd979bdSMark Fasheh 
276d85b20e4SJoel Becker 	spin_lock(&osb->osb_lock);
277d85b20e4SJoel Becker 	slot = __ocfs2_node_num_to_slot(si, node_num);
278d85b20e4SJoel Becker 	spin_unlock(&osb->osb_lock);
279d85b20e4SJoel Becker 
280d85b20e4SJoel Becker 	return slot;
281d85b20e4SJoel Becker }
282d85b20e4SJoel Becker 
ocfs2_slot_to_node_num_locked(struct ocfs2_super * osb,int slot_num,unsigned int * node_num)283d85b20e4SJoel Becker int ocfs2_slot_to_node_num_locked(struct ocfs2_super *osb, int slot_num,
284d85b20e4SJoel Becker 				  unsigned int *node_num)
285d85b20e4SJoel Becker {
286d85b20e4SJoel Becker 	struct ocfs2_slot_info *si = osb->slot_info;
287d85b20e4SJoel Becker 
288d85b20e4SJoel Becker 	assert_spin_locked(&osb->osb_lock);
289d85b20e4SJoel Becker 
290d85b20e4SJoel Becker 	BUG_ON(slot_num < 0);
291519a2861SDan Carpenter 	BUG_ON(slot_num >= osb->max_slots);
292d85b20e4SJoel Becker 
293fc881fa0SJoel Becker 	if (!si->si_slots[slot_num].sl_valid)
294d85b20e4SJoel Becker 		return -ENOENT;
295d85b20e4SJoel Becker 
296fc881fa0SJoel Becker 	*node_num = si->si_slots[slot_num].sl_node_num;
297d85b20e4SJoel Becker 	return 0;
298ccd979bdSMark Fasheh }
299ccd979bdSMark Fasheh 
__ocfs2_free_slot_info(struct ocfs2_slot_info * si)3008e8a4603SMark Fasheh static void __ocfs2_free_slot_info(struct ocfs2_slot_info *si)
3018e8a4603SMark Fasheh {
3021c8d9a6aSJoel Becker 	unsigned int i;
3031c8d9a6aSJoel Becker 
3048e8a4603SMark Fasheh 	if (si == NULL)
3058e8a4603SMark Fasheh 		return;
3068e8a4603SMark Fasheh 
3078e8a4603SMark Fasheh 	iput(si->si_inode);
3081c8d9a6aSJoel Becker 	if (si->si_bh) {
3091c8d9a6aSJoel Becker 		for (i = 0; i < si->si_blocks; i++) {
3101c8d9a6aSJoel Becker 			if (si->si_bh[i]) {
3111c8d9a6aSJoel Becker 				brelse(si->si_bh[i]);
3121c8d9a6aSJoel Becker 				si->si_bh[i] = NULL;
3131c8d9a6aSJoel Becker 			}
3141c8d9a6aSJoel Becker 		}
3151c8d9a6aSJoel Becker 		kfree(si->si_bh);
3161c8d9a6aSJoel Becker 	}
3178e8a4603SMark Fasheh 
3188e8a4603SMark Fasheh 	kfree(si);
3198e8a4603SMark Fasheh }
3208e8a4603SMark Fasheh 
ocfs2_clear_slot(struct ocfs2_super * osb,int slot_num)321fc881fa0SJoel Becker int ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num)
322ccd979bdSMark Fasheh {
3238e8a4603SMark Fasheh 	struct ocfs2_slot_info *si = osb->slot_info;
3248e8a4603SMark Fasheh 
3258e8a4603SMark Fasheh 	if (si == NULL)
3268e8a4603SMark Fasheh 		return 0;
3278e8a4603SMark Fasheh 
328d85b20e4SJoel Becker 	spin_lock(&osb->osb_lock);
329fc881fa0SJoel Becker 	ocfs2_invalidate_slot(si, slot_num);
330d85b20e4SJoel Becker 	spin_unlock(&osb->osb_lock);
3318e8a4603SMark Fasheh 
332386a2ef8SJoel Becker 	return ocfs2_update_disk_slot(osb, osb->slot_info, slot_num);
333ccd979bdSMark Fasheh }
334ccd979bdSMark Fasheh 
ocfs2_map_slot_buffers(struct ocfs2_super * osb,struct ocfs2_slot_info * si)3351c8d9a6aSJoel Becker static int ocfs2_map_slot_buffers(struct ocfs2_super *osb,
3361c8d9a6aSJoel Becker 				  struct ocfs2_slot_info *si)
3371c8d9a6aSJoel Becker {
3381c8d9a6aSJoel Becker 	int status = 0;
3391c8d9a6aSJoel Becker 	u64 blkno;
340f30d44f3SPoyo VL 	unsigned long long blocks, bytes = 0;
3411c8d9a6aSJoel Becker 	unsigned int i;
3421c8d9a6aSJoel Becker 	struct buffer_head *bh;
3431c8d9a6aSJoel Becker 
3441c8d9a6aSJoel Becker 	status = ocfs2_slot_map_physical_size(osb, si->si_inode, &bytes);
3451c8d9a6aSJoel Becker 	if (status)
3461c8d9a6aSJoel Becker 		goto bail;
3471c8d9a6aSJoel Becker 
3481c8d9a6aSJoel Becker 	blocks = ocfs2_blocks_for_bytes(si->si_inode->i_sb, bytes);
3491c8d9a6aSJoel Becker 	BUG_ON(blocks > UINT_MAX);
3501c8d9a6aSJoel Becker 	si->si_blocks = blocks;
3511c8d9a6aSJoel Becker 	if (!si->si_blocks)
3521c8d9a6aSJoel Becker 		goto bail;
3531c8d9a6aSJoel Becker 
354386a2ef8SJoel Becker 	if (si->si_extended)
355386a2ef8SJoel Becker 		si->si_slots_per_block =
356386a2ef8SJoel Becker 			(osb->sb->s_blocksize /
357386a2ef8SJoel Becker 			 sizeof(struct ocfs2_extended_slot));
358386a2ef8SJoel Becker 	else
359386a2ef8SJoel Becker 		si->si_slots_per_block = osb->sb->s_blocksize / sizeof(__le16);
360386a2ef8SJoel Becker 
361386a2ef8SJoel Becker 	/* The size checks above should ensure this */
362386a2ef8SJoel Becker 	BUG_ON((osb->max_slots / si->si_slots_per_block) > blocks);
363386a2ef8SJoel Becker 
364a8731086STao Ma 	trace_ocfs2_map_slot_buffers(bytes, si->si_blocks);
3651c8d9a6aSJoel Becker 
3661b7f8ba6SFabian Frederick 	si->si_bh = kcalloc(si->si_blocks, sizeof(struct buffer_head *),
3671c8d9a6aSJoel Becker 			    GFP_KERNEL);
3681c8d9a6aSJoel Becker 	if (!si->si_bh) {
3691c8d9a6aSJoel Becker 		status = -ENOMEM;
3701c8d9a6aSJoel Becker 		mlog_errno(status);
3711c8d9a6aSJoel Becker 		goto bail;
3721c8d9a6aSJoel Becker 	}
3731c8d9a6aSJoel Becker 
3741c8d9a6aSJoel Becker 	for (i = 0; i < si->si_blocks; i++) {
3751c8d9a6aSJoel Becker 		status = ocfs2_extent_map_get_blocks(si->si_inode, i,
3761c8d9a6aSJoel Becker 						     &blkno, NULL, NULL);
3771c8d9a6aSJoel Becker 		if (status < 0) {
3781c8d9a6aSJoel Becker 			mlog_errno(status);
3791c8d9a6aSJoel Becker 			goto bail;
3801c8d9a6aSJoel Becker 		}
3811c8d9a6aSJoel Becker 
382a8731086STao Ma 		trace_ocfs2_map_slot_buffers_block((unsigned long long)blkno, i);
3831c8d9a6aSJoel Becker 
3841c8d9a6aSJoel Becker 		bh = NULL;  /* Acquire a fresh bh */
3858cb471e8SJoel Becker 		status = ocfs2_read_blocks(INODE_CACHE(si->si_inode), blkno,
3868cb471e8SJoel Becker 					   1, &bh, OCFS2_BH_IGNORE_CACHE, NULL);
3871c8d9a6aSJoel Becker 		if (status < 0) {
3881c8d9a6aSJoel Becker 			mlog_errno(status);
3891c8d9a6aSJoel Becker 			goto bail;
3901c8d9a6aSJoel Becker 		}
3911c8d9a6aSJoel Becker 
3921c8d9a6aSJoel Becker 		si->si_bh[i] = bh;
3931c8d9a6aSJoel Becker 	}
3941c8d9a6aSJoel Becker 
3951c8d9a6aSJoel Becker bail:
3961c8d9a6aSJoel Becker 	return status;
3971c8d9a6aSJoel Becker }
3981c8d9a6aSJoel Becker 
ocfs2_init_slot_info(struct ocfs2_super * osb)399ccd979bdSMark Fasheh int ocfs2_init_slot_info(struct ocfs2_super *osb)
400ccd979bdSMark Fasheh {
401fc881fa0SJoel Becker 	int status;
402ccd979bdSMark Fasheh 	struct inode *inode = NULL;
403ccd979bdSMark Fasheh 	struct ocfs2_slot_info *si;
404ccd979bdSMark Fasheh 
405f402cf03SGustavo A. R. Silva 	si = kzalloc(struct_size(si, si_slots, osb->max_slots), GFP_KERNEL);
406ccd979bdSMark Fasheh 	if (!si) {
407ccd979bdSMark Fasheh 		status = -ENOMEM;
408ccd979bdSMark Fasheh 		mlog_errno(status);
409bb34ed21SMarkus Elfring 		return status;
410ccd979bdSMark Fasheh 	}
411ccd979bdSMark Fasheh 
412386a2ef8SJoel Becker 	si->si_extended = ocfs2_uses_extended_slot_map(osb);
413ccd979bdSMark Fasheh 	si->si_num_slots = osb->max_slots;
414ccd979bdSMark Fasheh 
415ccd979bdSMark Fasheh 	inode = ocfs2_get_system_file_inode(osb, SLOT_MAP_SYSTEM_INODE,
416ccd979bdSMark Fasheh 					    OCFS2_INVALID_SLOT);
417ccd979bdSMark Fasheh 	if (!inode) {
418ccd979bdSMark Fasheh 		status = -EINVAL;
419ccd979bdSMark Fasheh 		mlog_errno(status);
420ccd979bdSMark Fasheh 		goto bail;
421ccd979bdSMark Fasheh 	}
422ccd979bdSMark Fasheh 
423ccd979bdSMark Fasheh 	si->si_inode = inode;
4241c8d9a6aSJoel Becker 	status = ocfs2_map_slot_buffers(osb, si);
4251c8d9a6aSJoel Becker 	if (status < 0) {
4261c8d9a6aSJoel Becker 		mlog_errno(status);
4271c8d9a6aSJoel Becker 		goto bail;
4281c8d9a6aSJoel Becker 	}
4291c8d9a6aSJoel Becker 
430d85b20e4SJoel Becker 	osb->slot_info = (struct ocfs2_slot_info *)si;
431ccd979bdSMark Fasheh bail:
432fd90d4dfSMarkus Elfring 	if (status < 0)
4338e8a4603SMark Fasheh 		__ocfs2_free_slot_info(si);
434ccd979bdSMark Fasheh 
435ccd979bdSMark Fasheh 	return status;
436ccd979bdSMark Fasheh }
437ccd979bdSMark Fasheh 
ocfs2_free_slot_info(struct ocfs2_super * osb)4388e8a4603SMark Fasheh void ocfs2_free_slot_info(struct ocfs2_super *osb)
439ccd979bdSMark Fasheh {
4408e8a4603SMark Fasheh 	struct ocfs2_slot_info *si = osb->slot_info;
4418e8a4603SMark Fasheh 
4428e8a4603SMark Fasheh 	osb->slot_info = NULL;
4438e8a4603SMark Fasheh 	__ocfs2_free_slot_info(si);
444ccd979bdSMark Fasheh }
445ccd979bdSMark Fasheh 
ocfs2_find_slot(struct ocfs2_super * osb)446ccd979bdSMark Fasheh int ocfs2_find_slot(struct ocfs2_super *osb)
447ccd979bdSMark Fasheh {
448ccd979bdSMark Fasheh 	int status;
449fc881fa0SJoel Becker 	int slot;
450ccd979bdSMark Fasheh 	struct ocfs2_slot_info *si;
451ccd979bdSMark Fasheh 
452ccd979bdSMark Fasheh 	si = osb->slot_info;
453ccd979bdSMark Fasheh 
454d85b20e4SJoel Becker 	spin_lock(&osb->osb_lock);
455ccd979bdSMark Fasheh 	ocfs2_update_slot_info(si);
456ccd979bdSMark Fasheh 
457ccd979bdSMark Fasheh 	/* search for ourselves first and take the slot if it already
458ccd979bdSMark Fasheh 	 * exists. Perhaps we need to mark this in a variable for our
459ccd979bdSMark Fasheh 	 * own journal recovery? Possibly not, though we certainly
460ccd979bdSMark Fasheh 	 * need to warn to the user */
461ccd979bdSMark Fasheh 	slot = __ocfs2_node_num_to_slot(si, osb->node_num);
462fc881fa0SJoel Becker 	if (slot < 0) {
463ccd979bdSMark Fasheh 		/* if no slot yet, then just take 1st available
464ccd979bdSMark Fasheh 		 * one. */
465baf4661aSSunil Mushran 		slot = __ocfs2_find_empty_slot(si, osb->preferred_slot);
466fc881fa0SJoel Becker 		if (slot < 0) {
467d85b20e4SJoel Becker 			spin_unlock(&osb->osb_lock);
468ccd979bdSMark Fasheh 			mlog(ML_ERROR, "no free slots available!\n");
469ccd979bdSMark Fasheh 			status = -EINVAL;
470ccd979bdSMark Fasheh 			goto bail;
471ccd979bdSMark Fasheh 		}
472ccd979bdSMark Fasheh 	} else
473c80af0c2SJunxiao Bi 		printk(KERN_INFO "ocfs2: Slot %d on device (%s) was already "
474c80af0c2SJunxiao Bi 		       "allocated to this node!\n", slot, osb->dev_str);
475ccd979bdSMark Fasheh 
476fc881fa0SJoel Becker 	ocfs2_set_slot(si, slot, osb->node_num);
477ccd979bdSMark Fasheh 	osb->slot_num = slot;
478d85b20e4SJoel Becker 	spin_unlock(&osb->osb_lock);
479ccd979bdSMark Fasheh 
480a8731086STao Ma 	trace_ocfs2_find_slot(osb->slot_num);
481ccd979bdSMark Fasheh 
482386a2ef8SJoel Becker 	status = ocfs2_update_disk_slot(osb, si, osb->slot_num);
4831247017fSjiangyiwen 	if (status < 0) {
484ccd979bdSMark Fasheh 		mlog_errno(status);
4851247017fSjiangyiwen 		/*
4861247017fSjiangyiwen 		 * if write block failed, invalidate slot to avoid overwrite
4871247017fSjiangyiwen 		 * slot during dismount in case another node rightly has mounted
4881247017fSjiangyiwen 		 */
4891247017fSjiangyiwen 		spin_lock(&osb->osb_lock);
4901247017fSjiangyiwen 		ocfs2_invalidate_slot(si, osb->slot_num);
4911247017fSjiangyiwen 		osb->slot_num = OCFS2_INVALID_SLOT;
4921247017fSjiangyiwen 		spin_unlock(&osb->osb_lock);
4931247017fSjiangyiwen 	}
494ccd979bdSMark Fasheh 
495ccd979bdSMark Fasheh bail:
496ccd979bdSMark Fasheh 	return status;
497ccd979bdSMark Fasheh }
498ccd979bdSMark Fasheh 
ocfs2_put_slot(struct ocfs2_super * osb)499ccd979bdSMark Fasheh void ocfs2_put_slot(struct ocfs2_super *osb)
500ccd979bdSMark Fasheh {
501386a2ef8SJoel Becker 	int status, slot_num;
502ccd979bdSMark Fasheh 	struct ocfs2_slot_info *si = osb->slot_info;
503ccd979bdSMark Fasheh 
504ccd979bdSMark Fasheh 	if (!si)
505ccd979bdSMark Fasheh 		return;
506ccd979bdSMark Fasheh 
507d85b20e4SJoel Becker 	spin_lock(&osb->osb_lock);
508ccd979bdSMark Fasheh 	ocfs2_update_slot_info(si);
509ccd979bdSMark Fasheh 
510386a2ef8SJoel Becker 	slot_num = osb->slot_num;
511fc881fa0SJoel Becker 	ocfs2_invalidate_slot(si, osb->slot_num);
512ccd979bdSMark Fasheh 	osb->slot_num = OCFS2_INVALID_SLOT;
513d85b20e4SJoel Becker 	spin_unlock(&osb->osb_lock);
514ccd979bdSMark Fasheh 
515386a2ef8SJoel Becker 	status = ocfs2_update_disk_slot(osb, si, slot_num);
5168f9b1802SGuozhonghua 	if (status < 0)
517ccd979bdSMark Fasheh 		mlog_errno(status);
518ccd979bdSMark Fasheh 
5198e8a4603SMark Fasheh 	ocfs2_free_slot_info(osb);
520ccd979bdSMark Fasheh }
521