xref: /OK3568_Linux_fs/kernel/fs/nilfs2/alloc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * alloc.c - NILFS dat/inode allocator
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation.
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Originally written by Koji Sato.
8*4882a593Smuzhiyun  * Two allocators were unified by Ryusuke Konishi and Amagai Yoshiji.
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <linux/types.h>
12*4882a593Smuzhiyun #include <linux/buffer_head.h>
13*4882a593Smuzhiyun #include <linux/fs.h>
14*4882a593Smuzhiyun #include <linux/bitops.h>
15*4882a593Smuzhiyun #include <linux/slab.h>
16*4882a593Smuzhiyun #include "mdt.h"
17*4882a593Smuzhiyun #include "alloc.h"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun /**
21*4882a593Smuzhiyun  * nilfs_palloc_groups_per_desc_block - get the number of groups that a group
22*4882a593Smuzhiyun  *					descriptor block can maintain
23*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
24*4882a593Smuzhiyun  */
25*4882a593Smuzhiyun static inline unsigned long
nilfs_palloc_groups_per_desc_block(const struct inode * inode)26*4882a593Smuzhiyun nilfs_palloc_groups_per_desc_block(const struct inode *inode)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun 	return i_blocksize(inode) /
29*4882a593Smuzhiyun 		sizeof(struct nilfs_palloc_group_desc);
30*4882a593Smuzhiyun }
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun /**
33*4882a593Smuzhiyun  * nilfs_palloc_groups_count - get maximum number of groups
34*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
35*4882a593Smuzhiyun  */
36*4882a593Smuzhiyun static inline unsigned long
nilfs_palloc_groups_count(const struct inode * inode)37*4882a593Smuzhiyun nilfs_palloc_groups_count(const struct inode *inode)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun 	return 1UL << (BITS_PER_LONG - (inode->i_blkbits + 3 /* log2(8) */));
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun /**
43*4882a593Smuzhiyun  * nilfs_palloc_init_blockgroup - initialize private variables for allocator
44*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
45*4882a593Smuzhiyun  * @entry_size: size of the persistent object
46*4882a593Smuzhiyun  */
nilfs_palloc_init_blockgroup(struct inode * inode,unsigned int entry_size)47*4882a593Smuzhiyun int nilfs_palloc_init_blockgroup(struct inode *inode, unsigned int entry_size)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun 	struct nilfs_mdt_info *mi = NILFS_MDT(inode);
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	mi->mi_bgl = kmalloc(sizeof(*mi->mi_bgl), GFP_NOFS);
52*4882a593Smuzhiyun 	if (!mi->mi_bgl)
53*4882a593Smuzhiyun 		return -ENOMEM;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	bgl_lock_init(mi->mi_bgl);
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	nilfs_mdt_set_entry_size(inode, entry_size, 0);
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	mi->mi_blocks_per_group =
60*4882a593Smuzhiyun 		DIV_ROUND_UP(nilfs_palloc_entries_per_group(inode),
61*4882a593Smuzhiyun 			     mi->mi_entries_per_block) + 1;
62*4882a593Smuzhiyun 		/*
63*4882a593Smuzhiyun 		 * Number of blocks in a group including entry blocks
64*4882a593Smuzhiyun 		 * and a bitmap block
65*4882a593Smuzhiyun 		 */
66*4882a593Smuzhiyun 	mi->mi_blocks_per_desc_block =
67*4882a593Smuzhiyun 		nilfs_palloc_groups_per_desc_block(inode) *
68*4882a593Smuzhiyun 		mi->mi_blocks_per_group + 1;
69*4882a593Smuzhiyun 		/*
70*4882a593Smuzhiyun 		 * Number of blocks per descriptor including the
71*4882a593Smuzhiyun 		 * descriptor block
72*4882a593Smuzhiyun 		 */
73*4882a593Smuzhiyun 	return 0;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun /**
77*4882a593Smuzhiyun  * nilfs_palloc_group - get group number and offset from an entry number
78*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
79*4882a593Smuzhiyun  * @nr: serial number of the entry (e.g. inode number)
80*4882a593Smuzhiyun  * @offset: pointer to store offset number in the group
81*4882a593Smuzhiyun  */
nilfs_palloc_group(const struct inode * inode,__u64 nr,unsigned long * offset)82*4882a593Smuzhiyun static unsigned long nilfs_palloc_group(const struct inode *inode, __u64 nr,
83*4882a593Smuzhiyun 					unsigned long *offset)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun 	__u64 group = nr;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	*offset = do_div(group, nilfs_palloc_entries_per_group(inode));
88*4882a593Smuzhiyun 	return group;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun /**
92*4882a593Smuzhiyun  * nilfs_palloc_desc_blkoff - get block offset of a group descriptor block
93*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
94*4882a593Smuzhiyun  * @group: group number
95*4882a593Smuzhiyun  *
96*4882a593Smuzhiyun  * nilfs_palloc_desc_blkoff() returns block offset of the descriptor
97*4882a593Smuzhiyun  * block which contains a descriptor of the specified group.
98*4882a593Smuzhiyun  */
99*4882a593Smuzhiyun static unsigned long
nilfs_palloc_desc_blkoff(const struct inode * inode,unsigned long group)100*4882a593Smuzhiyun nilfs_palloc_desc_blkoff(const struct inode *inode, unsigned long group)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	unsigned long desc_block =
103*4882a593Smuzhiyun 		group / nilfs_palloc_groups_per_desc_block(inode);
104*4882a593Smuzhiyun 	return desc_block * NILFS_MDT(inode)->mi_blocks_per_desc_block;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun /**
108*4882a593Smuzhiyun  * nilfs_palloc_bitmap_blkoff - get block offset of a bitmap block
109*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
110*4882a593Smuzhiyun  * @group: group number
111*4882a593Smuzhiyun  *
112*4882a593Smuzhiyun  * nilfs_palloc_bitmap_blkoff() returns block offset of the bitmap
113*4882a593Smuzhiyun  * block used to allocate/deallocate entries in the specified group.
114*4882a593Smuzhiyun  */
115*4882a593Smuzhiyun static unsigned long
nilfs_palloc_bitmap_blkoff(const struct inode * inode,unsigned long group)116*4882a593Smuzhiyun nilfs_palloc_bitmap_blkoff(const struct inode *inode, unsigned long group)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun 	unsigned long desc_offset =
119*4882a593Smuzhiyun 		group % nilfs_palloc_groups_per_desc_block(inode);
120*4882a593Smuzhiyun 	return nilfs_palloc_desc_blkoff(inode, group) + 1 +
121*4882a593Smuzhiyun 		desc_offset * NILFS_MDT(inode)->mi_blocks_per_group;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun /**
125*4882a593Smuzhiyun  * nilfs_palloc_group_desc_nfrees - get the number of free entries in a group
126*4882a593Smuzhiyun  * @desc: pointer to descriptor structure for the group
127*4882a593Smuzhiyun  * @lock: spin lock protecting @desc
128*4882a593Smuzhiyun  */
129*4882a593Smuzhiyun static unsigned long
nilfs_palloc_group_desc_nfrees(const struct nilfs_palloc_group_desc * desc,spinlock_t * lock)130*4882a593Smuzhiyun nilfs_palloc_group_desc_nfrees(const struct nilfs_palloc_group_desc *desc,
131*4882a593Smuzhiyun 			       spinlock_t *lock)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun 	unsigned long nfree;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	spin_lock(lock);
136*4882a593Smuzhiyun 	nfree = le32_to_cpu(desc->pg_nfrees);
137*4882a593Smuzhiyun 	spin_unlock(lock);
138*4882a593Smuzhiyun 	return nfree;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun /**
142*4882a593Smuzhiyun  * nilfs_palloc_group_desc_add_entries - adjust count of free entries
143*4882a593Smuzhiyun  * @desc: pointer to descriptor structure for the group
144*4882a593Smuzhiyun  * @lock: spin lock protecting @desc
145*4882a593Smuzhiyun  * @n: delta to be added
146*4882a593Smuzhiyun  */
147*4882a593Smuzhiyun static u32
nilfs_palloc_group_desc_add_entries(struct nilfs_palloc_group_desc * desc,spinlock_t * lock,u32 n)148*4882a593Smuzhiyun nilfs_palloc_group_desc_add_entries(struct nilfs_palloc_group_desc *desc,
149*4882a593Smuzhiyun 				    spinlock_t *lock, u32 n)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun 	u32 nfree;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	spin_lock(lock);
154*4882a593Smuzhiyun 	le32_add_cpu(&desc->pg_nfrees, n);
155*4882a593Smuzhiyun 	nfree = le32_to_cpu(desc->pg_nfrees);
156*4882a593Smuzhiyun 	spin_unlock(lock);
157*4882a593Smuzhiyun 	return nfree;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun /**
161*4882a593Smuzhiyun  * nilfs_palloc_entry_blkoff - get block offset of an entry block
162*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
163*4882a593Smuzhiyun  * @nr: serial number of the entry (e.g. inode number)
164*4882a593Smuzhiyun  */
165*4882a593Smuzhiyun static unsigned long
nilfs_palloc_entry_blkoff(const struct inode * inode,__u64 nr)166*4882a593Smuzhiyun nilfs_palloc_entry_blkoff(const struct inode *inode, __u64 nr)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun 	unsigned long group, group_offset;
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	group = nilfs_palloc_group(inode, nr, &group_offset);
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	return nilfs_palloc_bitmap_blkoff(inode, group) + 1 +
173*4882a593Smuzhiyun 		group_offset / NILFS_MDT(inode)->mi_entries_per_block;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun /**
177*4882a593Smuzhiyun  * nilfs_palloc_desc_block_init - initialize buffer of a group descriptor block
178*4882a593Smuzhiyun  * @inode: inode of metadata file
179*4882a593Smuzhiyun  * @bh: buffer head of the buffer to be initialized
180*4882a593Smuzhiyun  * @kaddr: kernel address mapped for the page including the buffer
181*4882a593Smuzhiyun  */
nilfs_palloc_desc_block_init(struct inode * inode,struct buffer_head * bh,void * kaddr)182*4882a593Smuzhiyun static void nilfs_palloc_desc_block_init(struct inode *inode,
183*4882a593Smuzhiyun 					 struct buffer_head *bh, void *kaddr)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun 	struct nilfs_palloc_group_desc *desc = kaddr + bh_offset(bh);
186*4882a593Smuzhiyun 	unsigned long n = nilfs_palloc_groups_per_desc_block(inode);
187*4882a593Smuzhiyun 	__le32 nfrees;
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	nfrees = cpu_to_le32(nilfs_palloc_entries_per_group(inode));
190*4882a593Smuzhiyun 	while (n-- > 0) {
191*4882a593Smuzhiyun 		desc->pg_nfrees = nfrees;
192*4882a593Smuzhiyun 		desc++;
193*4882a593Smuzhiyun 	}
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun 
nilfs_palloc_get_block(struct inode * inode,unsigned long blkoff,int create,void (* init_block)(struct inode *,struct buffer_head *,void *),struct buffer_head ** bhp,struct nilfs_bh_assoc * prev,spinlock_t * lock)196*4882a593Smuzhiyun static int nilfs_palloc_get_block(struct inode *inode, unsigned long blkoff,
197*4882a593Smuzhiyun 				  int create,
198*4882a593Smuzhiyun 				  void (*init_block)(struct inode *,
199*4882a593Smuzhiyun 						     struct buffer_head *,
200*4882a593Smuzhiyun 						     void *),
201*4882a593Smuzhiyun 				  struct buffer_head **bhp,
202*4882a593Smuzhiyun 				  struct nilfs_bh_assoc *prev,
203*4882a593Smuzhiyun 				  spinlock_t *lock)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun 	int ret;
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	spin_lock(lock);
208*4882a593Smuzhiyun 	if (prev->bh && blkoff == prev->blkoff) {
209*4882a593Smuzhiyun 		get_bh(prev->bh);
210*4882a593Smuzhiyun 		*bhp = prev->bh;
211*4882a593Smuzhiyun 		spin_unlock(lock);
212*4882a593Smuzhiyun 		return 0;
213*4882a593Smuzhiyun 	}
214*4882a593Smuzhiyun 	spin_unlock(lock);
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	ret = nilfs_mdt_get_block(inode, blkoff, create, init_block, bhp);
217*4882a593Smuzhiyun 	if (!ret) {
218*4882a593Smuzhiyun 		spin_lock(lock);
219*4882a593Smuzhiyun 		/*
220*4882a593Smuzhiyun 		 * The following code must be safe for change of the
221*4882a593Smuzhiyun 		 * cache contents during the get block call.
222*4882a593Smuzhiyun 		 */
223*4882a593Smuzhiyun 		brelse(prev->bh);
224*4882a593Smuzhiyun 		get_bh(*bhp);
225*4882a593Smuzhiyun 		prev->bh = *bhp;
226*4882a593Smuzhiyun 		prev->blkoff = blkoff;
227*4882a593Smuzhiyun 		spin_unlock(lock);
228*4882a593Smuzhiyun 	}
229*4882a593Smuzhiyun 	return ret;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun /**
233*4882a593Smuzhiyun  * nilfs_palloc_delete_block - delete a block on the persistent allocator file
234*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
235*4882a593Smuzhiyun  * @blkoff: block offset
236*4882a593Smuzhiyun  * @prev: nilfs_bh_assoc struct of the last used buffer
237*4882a593Smuzhiyun  * @lock: spin lock protecting @prev
238*4882a593Smuzhiyun  */
nilfs_palloc_delete_block(struct inode * inode,unsigned long blkoff,struct nilfs_bh_assoc * prev,spinlock_t * lock)239*4882a593Smuzhiyun static int nilfs_palloc_delete_block(struct inode *inode, unsigned long blkoff,
240*4882a593Smuzhiyun 				     struct nilfs_bh_assoc *prev,
241*4882a593Smuzhiyun 				     spinlock_t *lock)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	spin_lock(lock);
244*4882a593Smuzhiyun 	if (prev->bh && blkoff == prev->blkoff) {
245*4882a593Smuzhiyun 		brelse(prev->bh);
246*4882a593Smuzhiyun 		prev->bh = NULL;
247*4882a593Smuzhiyun 	}
248*4882a593Smuzhiyun 	spin_unlock(lock);
249*4882a593Smuzhiyun 	return nilfs_mdt_delete_block(inode, blkoff);
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun /**
253*4882a593Smuzhiyun  * nilfs_palloc_get_desc_block - get buffer head of a group descriptor block
254*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
255*4882a593Smuzhiyun  * @group: group number
256*4882a593Smuzhiyun  * @create: create flag
257*4882a593Smuzhiyun  * @bhp: pointer to store the resultant buffer head
258*4882a593Smuzhiyun  */
nilfs_palloc_get_desc_block(struct inode * inode,unsigned long group,int create,struct buffer_head ** bhp)259*4882a593Smuzhiyun static int nilfs_palloc_get_desc_block(struct inode *inode,
260*4882a593Smuzhiyun 				       unsigned long group,
261*4882a593Smuzhiyun 				       int create, struct buffer_head **bhp)
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun 	struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	return nilfs_palloc_get_block(inode,
266*4882a593Smuzhiyun 				      nilfs_palloc_desc_blkoff(inode, group),
267*4882a593Smuzhiyun 				      create, nilfs_palloc_desc_block_init,
268*4882a593Smuzhiyun 				      bhp, &cache->prev_desc, &cache->lock);
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun /**
272*4882a593Smuzhiyun  * nilfs_palloc_get_bitmap_block - get buffer head of a bitmap block
273*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
274*4882a593Smuzhiyun  * @group: group number
275*4882a593Smuzhiyun  * @create: create flag
276*4882a593Smuzhiyun  * @bhp: pointer to store the resultant buffer head
277*4882a593Smuzhiyun  */
nilfs_palloc_get_bitmap_block(struct inode * inode,unsigned long group,int create,struct buffer_head ** bhp)278*4882a593Smuzhiyun static int nilfs_palloc_get_bitmap_block(struct inode *inode,
279*4882a593Smuzhiyun 					 unsigned long group,
280*4882a593Smuzhiyun 					 int create, struct buffer_head **bhp)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun 	struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	return nilfs_palloc_get_block(inode,
285*4882a593Smuzhiyun 				      nilfs_palloc_bitmap_blkoff(inode, group),
286*4882a593Smuzhiyun 				      create, NULL, bhp,
287*4882a593Smuzhiyun 				      &cache->prev_bitmap, &cache->lock);
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun /**
291*4882a593Smuzhiyun  * nilfs_palloc_delete_bitmap_block - delete a bitmap block
292*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
293*4882a593Smuzhiyun  * @group: group number
294*4882a593Smuzhiyun  */
nilfs_palloc_delete_bitmap_block(struct inode * inode,unsigned long group)295*4882a593Smuzhiyun static int nilfs_palloc_delete_bitmap_block(struct inode *inode,
296*4882a593Smuzhiyun 					    unsigned long group)
297*4882a593Smuzhiyun {
298*4882a593Smuzhiyun 	struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	return nilfs_palloc_delete_block(inode,
301*4882a593Smuzhiyun 					 nilfs_palloc_bitmap_blkoff(inode,
302*4882a593Smuzhiyun 								    group),
303*4882a593Smuzhiyun 					 &cache->prev_bitmap, &cache->lock);
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun /**
307*4882a593Smuzhiyun  * nilfs_palloc_get_entry_block - get buffer head of an entry block
308*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
309*4882a593Smuzhiyun  * @nr: serial number of the entry (e.g. inode number)
310*4882a593Smuzhiyun  * @create: create flag
311*4882a593Smuzhiyun  * @bhp: pointer to store the resultant buffer head
312*4882a593Smuzhiyun  */
nilfs_palloc_get_entry_block(struct inode * inode,__u64 nr,int create,struct buffer_head ** bhp)313*4882a593Smuzhiyun int nilfs_palloc_get_entry_block(struct inode *inode, __u64 nr,
314*4882a593Smuzhiyun 				 int create, struct buffer_head **bhp)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun 	struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	return nilfs_palloc_get_block(inode,
319*4882a593Smuzhiyun 				      nilfs_palloc_entry_blkoff(inode, nr),
320*4882a593Smuzhiyun 				      create, NULL, bhp,
321*4882a593Smuzhiyun 				      &cache->prev_entry, &cache->lock);
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun /**
325*4882a593Smuzhiyun  * nilfs_palloc_delete_entry_block - delete an entry block
326*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
327*4882a593Smuzhiyun  * @nr: serial number of the entry
328*4882a593Smuzhiyun  */
nilfs_palloc_delete_entry_block(struct inode * inode,__u64 nr)329*4882a593Smuzhiyun static int nilfs_palloc_delete_entry_block(struct inode *inode, __u64 nr)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun 	struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	return nilfs_palloc_delete_block(inode,
334*4882a593Smuzhiyun 					 nilfs_palloc_entry_blkoff(inode, nr),
335*4882a593Smuzhiyun 					 &cache->prev_entry, &cache->lock);
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun /**
339*4882a593Smuzhiyun  * nilfs_palloc_block_get_group_desc - get kernel address of a group descriptor
340*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
341*4882a593Smuzhiyun  * @group: group number
342*4882a593Smuzhiyun  * @bh: buffer head of the buffer storing the group descriptor block
343*4882a593Smuzhiyun  * @kaddr: kernel address mapped for the page including the buffer
344*4882a593Smuzhiyun  */
345*4882a593Smuzhiyun static struct nilfs_palloc_group_desc *
nilfs_palloc_block_get_group_desc(const struct inode * inode,unsigned long group,const struct buffer_head * bh,void * kaddr)346*4882a593Smuzhiyun nilfs_palloc_block_get_group_desc(const struct inode *inode,
347*4882a593Smuzhiyun 				  unsigned long group,
348*4882a593Smuzhiyun 				  const struct buffer_head *bh, void *kaddr)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun 	return (struct nilfs_palloc_group_desc *)(kaddr + bh_offset(bh)) +
351*4882a593Smuzhiyun 		group % nilfs_palloc_groups_per_desc_block(inode);
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun /**
355*4882a593Smuzhiyun  * nilfs_palloc_block_get_entry - get kernel address of an entry
356*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
357*4882a593Smuzhiyun  * @nr: serial number of the entry (e.g. inode number)
358*4882a593Smuzhiyun  * @bh: buffer head of the buffer storing the entry block
359*4882a593Smuzhiyun  * @kaddr: kernel address mapped for the page including the buffer
360*4882a593Smuzhiyun  */
nilfs_palloc_block_get_entry(const struct inode * inode,__u64 nr,const struct buffer_head * bh,void * kaddr)361*4882a593Smuzhiyun void *nilfs_palloc_block_get_entry(const struct inode *inode, __u64 nr,
362*4882a593Smuzhiyun 				   const struct buffer_head *bh, void *kaddr)
363*4882a593Smuzhiyun {
364*4882a593Smuzhiyun 	unsigned long entry_offset, group_offset;
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	nilfs_palloc_group(inode, nr, &group_offset);
367*4882a593Smuzhiyun 	entry_offset = group_offset % NILFS_MDT(inode)->mi_entries_per_block;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	return kaddr + bh_offset(bh) +
370*4882a593Smuzhiyun 		entry_offset * NILFS_MDT(inode)->mi_entry_size;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun /**
374*4882a593Smuzhiyun  * nilfs_palloc_find_available_slot - find available slot in a group
375*4882a593Smuzhiyun  * @bitmap: bitmap of the group
376*4882a593Smuzhiyun  * @target: offset number of an entry in the group (start point)
377*4882a593Smuzhiyun  * @bsize: size in bits
378*4882a593Smuzhiyun  * @lock: spin lock protecting @bitmap
379*4882a593Smuzhiyun  */
nilfs_palloc_find_available_slot(unsigned char * bitmap,unsigned long target,unsigned int bsize,spinlock_t * lock)380*4882a593Smuzhiyun static int nilfs_palloc_find_available_slot(unsigned char *bitmap,
381*4882a593Smuzhiyun 					    unsigned long target,
382*4882a593Smuzhiyun 					    unsigned int bsize,
383*4882a593Smuzhiyun 					    spinlock_t *lock)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun 	int pos, end = bsize;
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	if (likely(target < bsize)) {
388*4882a593Smuzhiyun 		pos = target;
389*4882a593Smuzhiyun 		do {
390*4882a593Smuzhiyun 			pos = nilfs_find_next_zero_bit(bitmap, end, pos);
391*4882a593Smuzhiyun 			if (pos >= end)
392*4882a593Smuzhiyun 				break;
393*4882a593Smuzhiyun 			if (!nilfs_set_bit_atomic(lock, pos, bitmap))
394*4882a593Smuzhiyun 				return pos;
395*4882a593Smuzhiyun 		} while (++pos < end);
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 		end = target;
398*4882a593Smuzhiyun 	}
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	/* wrap around */
401*4882a593Smuzhiyun 	for (pos = 0; pos < end; pos++) {
402*4882a593Smuzhiyun 		pos = nilfs_find_next_zero_bit(bitmap, end, pos);
403*4882a593Smuzhiyun 		if (pos >= end)
404*4882a593Smuzhiyun 			break;
405*4882a593Smuzhiyun 		if (!nilfs_set_bit_atomic(lock, pos, bitmap))
406*4882a593Smuzhiyun 			return pos;
407*4882a593Smuzhiyun 	}
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	return -ENOSPC;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun /**
413*4882a593Smuzhiyun  * nilfs_palloc_rest_groups_in_desc_block - get the remaining number of groups
414*4882a593Smuzhiyun  *					    in a group descriptor block
415*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
416*4882a593Smuzhiyun  * @curr: current group number
417*4882a593Smuzhiyun  * @max: maximum number of groups
418*4882a593Smuzhiyun  */
419*4882a593Smuzhiyun static unsigned long
nilfs_palloc_rest_groups_in_desc_block(const struct inode * inode,unsigned long curr,unsigned long max)420*4882a593Smuzhiyun nilfs_palloc_rest_groups_in_desc_block(const struct inode *inode,
421*4882a593Smuzhiyun 				       unsigned long curr, unsigned long max)
422*4882a593Smuzhiyun {
423*4882a593Smuzhiyun 	return min_t(unsigned long,
424*4882a593Smuzhiyun 		     nilfs_palloc_groups_per_desc_block(inode) -
425*4882a593Smuzhiyun 		     curr % nilfs_palloc_groups_per_desc_block(inode),
426*4882a593Smuzhiyun 		     max - curr + 1);
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun /**
430*4882a593Smuzhiyun  * nilfs_palloc_count_desc_blocks - count descriptor blocks number
431*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
432*4882a593Smuzhiyun  * @desc_blocks: descriptor blocks number [out]
433*4882a593Smuzhiyun  */
nilfs_palloc_count_desc_blocks(struct inode * inode,unsigned long * desc_blocks)434*4882a593Smuzhiyun static int nilfs_palloc_count_desc_blocks(struct inode *inode,
435*4882a593Smuzhiyun 					    unsigned long *desc_blocks)
436*4882a593Smuzhiyun {
437*4882a593Smuzhiyun 	__u64 blknum;
438*4882a593Smuzhiyun 	int ret;
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 	ret = nilfs_bmap_last_key(NILFS_I(inode)->i_bmap, &blknum);
441*4882a593Smuzhiyun 	if (likely(!ret))
442*4882a593Smuzhiyun 		*desc_blocks = DIV_ROUND_UP(
443*4882a593Smuzhiyun 			(unsigned long)blknum,
444*4882a593Smuzhiyun 			NILFS_MDT(inode)->mi_blocks_per_desc_block);
445*4882a593Smuzhiyun 	return ret;
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun /**
449*4882a593Smuzhiyun  * nilfs_palloc_mdt_file_can_grow - check potential opportunity for
450*4882a593Smuzhiyun  *					MDT file growing
451*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
452*4882a593Smuzhiyun  * @desc_blocks: known current descriptor blocks count
453*4882a593Smuzhiyun  */
nilfs_palloc_mdt_file_can_grow(struct inode * inode,unsigned long desc_blocks)454*4882a593Smuzhiyun static inline bool nilfs_palloc_mdt_file_can_grow(struct inode *inode,
455*4882a593Smuzhiyun 						    unsigned long desc_blocks)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun 	return (nilfs_palloc_groups_per_desc_block(inode) * desc_blocks) <
458*4882a593Smuzhiyun 			nilfs_palloc_groups_count(inode);
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun /**
462*4882a593Smuzhiyun  * nilfs_palloc_count_max_entries - count max number of entries that can be
463*4882a593Smuzhiyun  *					described by descriptor blocks count
464*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
465*4882a593Smuzhiyun  * @nused: current number of used entries
466*4882a593Smuzhiyun  * @nmaxp: max number of entries [out]
467*4882a593Smuzhiyun  */
nilfs_palloc_count_max_entries(struct inode * inode,u64 nused,u64 * nmaxp)468*4882a593Smuzhiyun int nilfs_palloc_count_max_entries(struct inode *inode, u64 nused, u64 *nmaxp)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun 	unsigned long desc_blocks = 0;
471*4882a593Smuzhiyun 	u64 entries_per_desc_block, nmax;
472*4882a593Smuzhiyun 	int err;
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun 	err = nilfs_palloc_count_desc_blocks(inode, &desc_blocks);
475*4882a593Smuzhiyun 	if (unlikely(err))
476*4882a593Smuzhiyun 		return err;
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	entries_per_desc_block = (u64)nilfs_palloc_entries_per_group(inode) *
479*4882a593Smuzhiyun 				nilfs_palloc_groups_per_desc_block(inode);
480*4882a593Smuzhiyun 	nmax = entries_per_desc_block * desc_blocks;
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	if (nused == nmax &&
483*4882a593Smuzhiyun 			nilfs_palloc_mdt_file_can_grow(inode, desc_blocks))
484*4882a593Smuzhiyun 		nmax += entries_per_desc_block;
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 	if (nused > nmax)
487*4882a593Smuzhiyun 		return -ERANGE;
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun 	*nmaxp = nmax;
490*4882a593Smuzhiyun 	return 0;
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun /**
494*4882a593Smuzhiyun  * nilfs_palloc_prepare_alloc_entry - prepare to allocate a persistent object
495*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
496*4882a593Smuzhiyun  * @req: nilfs_palloc_req structure exchanged for the allocation
497*4882a593Smuzhiyun  */
nilfs_palloc_prepare_alloc_entry(struct inode * inode,struct nilfs_palloc_req * req)498*4882a593Smuzhiyun int nilfs_palloc_prepare_alloc_entry(struct inode *inode,
499*4882a593Smuzhiyun 				     struct nilfs_palloc_req *req)
500*4882a593Smuzhiyun {
501*4882a593Smuzhiyun 	struct buffer_head *desc_bh, *bitmap_bh;
502*4882a593Smuzhiyun 	struct nilfs_palloc_group_desc *desc;
503*4882a593Smuzhiyun 	unsigned char *bitmap;
504*4882a593Smuzhiyun 	void *desc_kaddr, *bitmap_kaddr;
505*4882a593Smuzhiyun 	unsigned long group, maxgroup, ngroups;
506*4882a593Smuzhiyun 	unsigned long group_offset, maxgroup_offset;
507*4882a593Smuzhiyun 	unsigned long n, entries_per_group;
508*4882a593Smuzhiyun 	unsigned long i, j;
509*4882a593Smuzhiyun 	spinlock_t *lock;
510*4882a593Smuzhiyun 	int pos, ret;
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun 	ngroups = nilfs_palloc_groups_count(inode);
513*4882a593Smuzhiyun 	maxgroup = ngroups - 1;
514*4882a593Smuzhiyun 	group = nilfs_palloc_group(inode, req->pr_entry_nr, &group_offset);
515*4882a593Smuzhiyun 	entries_per_group = nilfs_palloc_entries_per_group(inode);
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	for (i = 0; i < ngroups; i += n) {
518*4882a593Smuzhiyun 		if (group >= ngroups) {
519*4882a593Smuzhiyun 			/* wrap around */
520*4882a593Smuzhiyun 			group = 0;
521*4882a593Smuzhiyun 			maxgroup = nilfs_palloc_group(inode, req->pr_entry_nr,
522*4882a593Smuzhiyun 						      &maxgroup_offset) - 1;
523*4882a593Smuzhiyun 		}
524*4882a593Smuzhiyun 		ret = nilfs_palloc_get_desc_block(inode, group, 1, &desc_bh);
525*4882a593Smuzhiyun 		if (ret < 0)
526*4882a593Smuzhiyun 			return ret;
527*4882a593Smuzhiyun 		desc_kaddr = kmap(desc_bh->b_page);
528*4882a593Smuzhiyun 		desc = nilfs_palloc_block_get_group_desc(
529*4882a593Smuzhiyun 			inode, group, desc_bh, desc_kaddr);
530*4882a593Smuzhiyun 		n = nilfs_palloc_rest_groups_in_desc_block(inode, group,
531*4882a593Smuzhiyun 							   maxgroup);
532*4882a593Smuzhiyun 		for (j = 0; j < n; j++, desc++, group++) {
533*4882a593Smuzhiyun 			lock = nilfs_mdt_bgl_lock(inode, group);
534*4882a593Smuzhiyun 			if (nilfs_palloc_group_desc_nfrees(desc, lock) > 0) {
535*4882a593Smuzhiyun 				ret = nilfs_palloc_get_bitmap_block(
536*4882a593Smuzhiyun 					inode, group, 1, &bitmap_bh);
537*4882a593Smuzhiyun 				if (ret < 0)
538*4882a593Smuzhiyun 					goto out_desc;
539*4882a593Smuzhiyun 				bitmap_kaddr = kmap(bitmap_bh->b_page);
540*4882a593Smuzhiyun 				bitmap = bitmap_kaddr + bh_offset(bitmap_bh);
541*4882a593Smuzhiyun 				pos = nilfs_palloc_find_available_slot(
542*4882a593Smuzhiyun 					bitmap, group_offset,
543*4882a593Smuzhiyun 					entries_per_group, lock);
544*4882a593Smuzhiyun 				if (pos >= 0) {
545*4882a593Smuzhiyun 					/* found a free entry */
546*4882a593Smuzhiyun 					nilfs_palloc_group_desc_add_entries(
547*4882a593Smuzhiyun 						desc, lock, -1);
548*4882a593Smuzhiyun 					req->pr_entry_nr =
549*4882a593Smuzhiyun 						entries_per_group * group + pos;
550*4882a593Smuzhiyun 					kunmap(desc_bh->b_page);
551*4882a593Smuzhiyun 					kunmap(bitmap_bh->b_page);
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 					req->pr_desc_bh = desc_bh;
554*4882a593Smuzhiyun 					req->pr_bitmap_bh = bitmap_bh;
555*4882a593Smuzhiyun 					return 0;
556*4882a593Smuzhiyun 				}
557*4882a593Smuzhiyun 				kunmap(bitmap_bh->b_page);
558*4882a593Smuzhiyun 				brelse(bitmap_bh);
559*4882a593Smuzhiyun 			}
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun 			group_offset = 0;
562*4882a593Smuzhiyun 		}
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 		kunmap(desc_bh->b_page);
565*4882a593Smuzhiyun 		brelse(desc_bh);
566*4882a593Smuzhiyun 	}
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 	/* no entries left */
569*4882a593Smuzhiyun 	return -ENOSPC;
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun  out_desc:
572*4882a593Smuzhiyun 	kunmap(desc_bh->b_page);
573*4882a593Smuzhiyun 	brelse(desc_bh);
574*4882a593Smuzhiyun 	return ret;
575*4882a593Smuzhiyun }
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun /**
578*4882a593Smuzhiyun  * nilfs_palloc_commit_alloc_entry - finish allocation of a persistent object
579*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
580*4882a593Smuzhiyun  * @req: nilfs_palloc_req structure exchanged for the allocation
581*4882a593Smuzhiyun  */
nilfs_palloc_commit_alloc_entry(struct inode * inode,struct nilfs_palloc_req * req)582*4882a593Smuzhiyun void nilfs_palloc_commit_alloc_entry(struct inode *inode,
583*4882a593Smuzhiyun 				     struct nilfs_palloc_req *req)
584*4882a593Smuzhiyun {
585*4882a593Smuzhiyun 	mark_buffer_dirty(req->pr_bitmap_bh);
586*4882a593Smuzhiyun 	mark_buffer_dirty(req->pr_desc_bh);
587*4882a593Smuzhiyun 	nilfs_mdt_mark_dirty(inode);
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	brelse(req->pr_bitmap_bh);
590*4882a593Smuzhiyun 	brelse(req->pr_desc_bh);
591*4882a593Smuzhiyun }
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun /**
594*4882a593Smuzhiyun  * nilfs_palloc_commit_free_entry - finish deallocating a persistent object
595*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
596*4882a593Smuzhiyun  * @req: nilfs_palloc_req structure exchanged for the removal
597*4882a593Smuzhiyun  */
nilfs_palloc_commit_free_entry(struct inode * inode,struct nilfs_palloc_req * req)598*4882a593Smuzhiyun void nilfs_palloc_commit_free_entry(struct inode *inode,
599*4882a593Smuzhiyun 				    struct nilfs_palloc_req *req)
600*4882a593Smuzhiyun {
601*4882a593Smuzhiyun 	struct nilfs_palloc_group_desc *desc;
602*4882a593Smuzhiyun 	unsigned long group, group_offset;
603*4882a593Smuzhiyun 	unsigned char *bitmap;
604*4882a593Smuzhiyun 	void *desc_kaddr, *bitmap_kaddr;
605*4882a593Smuzhiyun 	spinlock_t *lock;
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun 	group = nilfs_palloc_group(inode, req->pr_entry_nr, &group_offset);
608*4882a593Smuzhiyun 	desc_kaddr = kmap(req->pr_desc_bh->b_page);
609*4882a593Smuzhiyun 	desc = nilfs_palloc_block_get_group_desc(inode, group,
610*4882a593Smuzhiyun 						 req->pr_desc_bh, desc_kaddr);
611*4882a593Smuzhiyun 	bitmap_kaddr = kmap(req->pr_bitmap_bh->b_page);
612*4882a593Smuzhiyun 	bitmap = bitmap_kaddr + bh_offset(req->pr_bitmap_bh);
613*4882a593Smuzhiyun 	lock = nilfs_mdt_bgl_lock(inode, group);
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun 	if (!nilfs_clear_bit_atomic(lock, group_offset, bitmap))
616*4882a593Smuzhiyun 		nilfs_warn(inode->i_sb,
617*4882a593Smuzhiyun 			   "%s (ino=%lu): entry number %llu already freed",
618*4882a593Smuzhiyun 			   __func__, inode->i_ino,
619*4882a593Smuzhiyun 			   (unsigned long long)req->pr_entry_nr);
620*4882a593Smuzhiyun 	else
621*4882a593Smuzhiyun 		nilfs_palloc_group_desc_add_entries(desc, lock, 1);
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	kunmap(req->pr_bitmap_bh->b_page);
624*4882a593Smuzhiyun 	kunmap(req->pr_desc_bh->b_page);
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun 	mark_buffer_dirty(req->pr_desc_bh);
627*4882a593Smuzhiyun 	mark_buffer_dirty(req->pr_bitmap_bh);
628*4882a593Smuzhiyun 	nilfs_mdt_mark_dirty(inode);
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun 	brelse(req->pr_bitmap_bh);
631*4882a593Smuzhiyun 	brelse(req->pr_desc_bh);
632*4882a593Smuzhiyun }
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun /**
635*4882a593Smuzhiyun  * nilfs_palloc_abort_alloc_entry - cancel allocation of a persistent object
636*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
637*4882a593Smuzhiyun  * @req: nilfs_palloc_req structure exchanged for the allocation
638*4882a593Smuzhiyun  */
nilfs_palloc_abort_alloc_entry(struct inode * inode,struct nilfs_palloc_req * req)639*4882a593Smuzhiyun void nilfs_palloc_abort_alloc_entry(struct inode *inode,
640*4882a593Smuzhiyun 				    struct nilfs_palloc_req *req)
641*4882a593Smuzhiyun {
642*4882a593Smuzhiyun 	struct nilfs_palloc_group_desc *desc;
643*4882a593Smuzhiyun 	void *desc_kaddr, *bitmap_kaddr;
644*4882a593Smuzhiyun 	unsigned char *bitmap;
645*4882a593Smuzhiyun 	unsigned long group, group_offset;
646*4882a593Smuzhiyun 	spinlock_t *lock;
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	group = nilfs_palloc_group(inode, req->pr_entry_nr, &group_offset);
649*4882a593Smuzhiyun 	desc_kaddr = kmap(req->pr_desc_bh->b_page);
650*4882a593Smuzhiyun 	desc = nilfs_palloc_block_get_group_desc(inode, group,
651*4882a593Smuzhiyun 						 req->pr_desc_bh, desc_kaddr);
652*4882a593Smuzhiyun 	bitmap_kaddr = kmap(req->pr_bitmap_bh->b_page);
653*4882a593Smuzhiyun 	bitmap = bitmap_kaddr + bh_offset(req->pr_bitmap_bh);
654*4882a593Smuzhiyun 	lock = nilfs_mdt_bgl_lock(inode, group);
655*4882a593Smuzhiyun 
656*4882a593Smuzhiyun 	if (!nilfs_clear_bit_atomic(lock, group_offset, bitmap))
657*4882a593Smuzhiyun 		nilfs_warn(inode->i_sb,
658*4882a593Smuzhiyun 			   "%s (ino=%lu): entry number %llu already freed",
659*4882a593Smuzhiyun 			   __func__, inode->i_ino,
660*4882a593Smuzhiyun 			   (unsigned long long)req->pr_entry_nr);
661*4882a593Smuzhiyun 	else
662*4882a593Smuzhiyun 		nilfs_palloc_group_desc_add_entries(desc, lock, 1);
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	kunmap(req->pr_bitmap_bh->b_page);
665*4882a593Smuzhiyun 	kunmap(req->pr_desc_bh->b_page);
666*4882a593Smuzhiyun 
667*4882a593Smuzhiyun 	brelse(req->pr_bitmap_bh);
668*4882a593Smuzhiyun 	brelse(req->pr_desc_bh);
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	req->pr_entry_nr = 0;
671*4882a593Smuzhiyun 	req->pr_bitmap_bh = NULL;
672*4882a593Smuzhiyun 	req->pr_desc_bh = NULL;
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun /**
676*4882a593Smuzhiyun  * nilfs_palloc_prepare_free_entry - prepare to deallocate a persistent object
677*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
678*4882a593Smuzhiyun  * @req: nilfs_palloc_req structure exchanged for the removal
679*4882a593Smuzhiyun  */
nilfs_palloc_prepare_free_entry(struct inode * inode,struct nilfs_palloc_req * req)680*4882a593Smuzhiyun int nilfs_palloc_prepare_free_entry(struct inode *inode,
681*4882a593Smuzhiyun 				    struct nilfs_palloc_req *req)
682*4882a593Smuzhiyun {
683*4882a593Smuzhiyun 	struct buffer_head *desc_bh, *bitmap_bh;
684*4882a593Smuzhiyun 	unsigned long group, group_offset;
685*4882a593Smuzhiyun 	int ret;
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun 	group = nilfs_palloc_group(inode, req->pr_entry_nr, &group_offset);
688*4882a593Smuzhiyun 	ret = nilfs_palloc_get_desc_block(inode, group, 1, &desc_bh);
689*4882a593Smuzhiyun 	if (ret < 0)
690*4882a593Smuzhiyun 		return ret;
691*4882a593Smuzhiyun 	ret = nilfs_palloc_get_bitmap_block(inode, group, 1, &bitmap_bh);
692*4882a593Smuzhiyun 	if (ret < 0) {
693*4882a593Smuzhiyun 		brelse(desc_bh);
694*4882a593Smuzhiyun 		return ret;
695*4882a593Smuzhiyun 	}
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun 	req->pr_desc_bh = desc_bh;
698*4882a593Smuzhiyun 	req->pr_bitmap_bh = bitmap_bh;
699*4882a593Smuzhiyun 	return 0;
700*4882a593Smuzhiyun }
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun /**
703*4882a593Smuzhiyun  * nilfs_palloc_abort_free_entry - cancel deallocating a persistent object
704*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
705*4882a593Smuzhiyun  * @req: nilfs_palloc_req structure exchanged for the removal
706*4882a593Smuzhiyun  */
nilfs_palloc_abort_free_entry(struct inode * inode,struct nilfs_palloc_req * req)707*4882a593Smuzhiyun void nilfs_palloc_abort_free_entry(struct inode *inode,
708*4882a593Smuzhiyun 				   struct nilfs_palloc_req *req)
709*4882a593Smuzhiyun {
710*4882a593Smuzhiyun 	brelse(req->pr_bitmap_bh);
711*4882a593Smuzhiyun 	brelse(req->pr_desc_bh);
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun 	req->pr_entry_nr = 0;
714*4882a593Smuzhiyun 	req->pr_bitmap_bh = NULL;
715*4882a593Smuzhiyun 	req->pr_desc_bh = NULL;
716*4882a593Smuzhiyun }
717*4882a593Smuzhiyun 
718*4882a593Smuzhiyun /**
719*4882a593Smuzhiyun  * nilfs_palloc_freev - deallocate a set of persistent objects
720*4882a593Smuzhiyun  * @inode: inode of metadata file using this allocator
721*4882a593Smuzhiyun  * @entry_nrs: array of entry numbers to be deallocated
722*4882a593Smuzhiyun  * @nitems: number of entries stored in @entry_nrs
723*4882a593Smuzhiyun  */
nilfs_palloc_freev(struct inode * inode,__u64 * entry_nrs,size_t nitems)724*4882a593Smuzhiyun int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems)
725*4882a593Smuzhiyun {
726*4882a593Smuzhiyun 	struct buffer_head *desc_bh, *bitmap_bh;
727*4882a593Smuzhiyun 	struct nilfs_palloc_group_desc *desc;
728*4882a593Smuzhiyun 	unsigned char *bitmap;
729*4882a593Smuzhiyun 	void *desc_kaddr, *bitmap_kaddr;
730*4882a593Smuzhiyun 	unsigned long group, group_offset;
731*4882a593Smuzhiyun 	__u64 group_min_nr, last_nrs[8];
732*4882a593Smuzhiyun 	const unsigned long epg = nilfs_palloc_entries_per_group(inode);
733*4882a593Smuzhiyun 	const unsigned int epb = NILFS_MDT(inode)->mi_entries_per_block;
734*4882a593Smuzhiyun 	unsigned int entry_start, end, pos;
735*4882a593Smuzhiyun 	spinlock_t *lock;
736*4882a593Smuzhiyun 	int i, j, k, ret;
737*4882a593Smuzhiyun 	u32 nfree;
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	for (i = 0; i < nitems; i = j) {
740*4882a593Smuzhiyun 		int change_group = false;
741*4882a593Smuzhiyun 		int nempties = 0, n = 0;
742*4882a593Smuzhiyun 
743*4882a593Smuzhiyun 		group = nilfs_palloc_group(inode, entry_nrs[i], &group_offset);
744*4882a593Smuzhiyun 		ret = nilfs_palloc_get_desc_block(inode, group, 0, &desc_bh);
745*4882a593Smuzhiyun 		if (ret < 0)
746*4882a593Smuzhiyun 			return ret;
747*4882a593Smuzhiyun 		ret = nilfs_palloc_get_bitmap_block(inode, group, 0,
748*4882a593Smuzhiyun 						    &bitmap_bh);
749*4882a593Smuzhiyun 		if (ret < 0) {
750*4882a593Smuzhiyun 			brelse(desc_bh);
751*4882a593Smuzhiyun 			return ret;
752*4882a593Smuzhiyun 		}
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun 		/* Get the first entry number of the group */
755*4882a593Smuzhiyun 		group_min_nr = (__u64)group * epg;
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun 		bitmap_kaddr = kmap(bitmap_bh->b_page);
758*4882a593Smuzhiyun 		bitmap = bitmap_kaddr + bh_offset(bitmap_bh);
759*4882a593Smuzhiyun 		lock = nilfs_mdt_bgl_lock(inode, group);
760*4882a593Smuzhiyun 
761*4882a593Smuzhiyun 		j = i;
762*4882a593Smuzhiyun 		entry_start = rounddown(group_offset, epb);
763*4882a593Smuzhiyun 		do {
764*4882a593Smuzhiyun 			if (!nilfs_clear_bit_atomic(lock, group_offset,
765*4882a593Smuzhiyun 						    bitmap)) {
766*4882a593Smuzhiyun 				nilfs_warn(inode->i_sb,
767*4882a593Smuzhiyun 					   "%s (ino=%lu): entry number %llu already freed",
768*4882a593Smuzhiyun 					   __func__, inode->i_ino,
769*4882a593Smuzhiyun 					   (unsigned long long)entry_nrs[j]);
770*4882a593Smuzhiyun 			} else {
771*4882a593Smuzhiyun 				n++;
772*4882a593Smuzhiyun 			}
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun 			j++;
775*4882a593Smuzhiyun 			if (j >= nitems || entry_nrs[j] < group_min_nr ||
776*4882a593Smuzhiyun 			    entry_nrs[j] >= group_min_nr + epg) {
777*4882a593Smuzhiyun 				change_group = true;
778*4882a593Smuzhiyun 			} else {
779*4882a593Smuzhiyun 				group_offset = entry_nrs[j] - group_min_nr;
780*4882a593Smuzhiyun 				if (group_offset >= entry_start &&
781*4882a593Smuzhiyun 				    group_offset < entry_start + epb) {
782*4882a593Smuzhiyun 					/* This entry is in the same block */
783*4882a593Smuzhiyun 					continue;
784*4882a593Smuzhiyun 				}
785*4882a593Smuzhiyun 			}
786*4882a593Smuzhiyun 
787*4882a593Smuzhiyun 			/* Test if the entry block is empty or not */
788*4882a593Smuzhiyun 			end = entry_start + epb;
789*4882a593Smuzhiyun 			pos = nilfs_find_next_bit(bitmap, end, entry_start);
790*4882a593Smuzhiyun 			if (pos >= end) {
791*4882a593Smuzhiyun 				last_nrs[nempties++] = entry_nrs[j - 1];
792*4882a593Smuzhiyun 				if (nempties >= ARRAY_SIZE(last_nrs))
793*4882a593Smuzhiyun 					break;
794*4882a593Smuzhiyun 			}
795*4882a593Smuzhiyun 
796*4882a593Smuzhiyun 			if (change_group)
797*4882a593Smuzhiyun 				break;
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun 			/* Go on to the next entry block */
800*4882a593Smuzhiyun 			entry_start = rounddown(group_offset, epb);
801*4882a593Smuzhiyun 		} while (true);
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun 		kunmap(bitmap_bh->b_page);
804*4882a593Smuzhiyun 		mark_buffer_dirty(bitmap_bh);
805*4882a593Smuzhiyun 		brelse(bitmap_bh);
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun 		for (k = 0; k < nempties; k++) {
808*4882a593Smuzhiyun 			ret = nilfs_palloc_delete_entry_block(inode,
809*4882a593Smuzhiyun 							      last_nrs[k]);
810*4882a593Smuzhiyun 			if (ret && ret != -ENOENT)
811*4882a593Smuzhiyun 				nilfs_warn(inode->i_sb,
812*4882a593Smuzhiyun 					   "error %d deleting block that object (entry=%llu, ino=%lu) belongs to",
813*4882a593Smuzhiyun 					   ret, (unsigned long long)last_nrs[k],
814*4882a593Smuzhiyun 					   inode->i_ino);
815*4882a593Smuzhiyun 		}
816*4882a593Smuzhiyun 
817*4882a593Smuzhiyun 		desc_kaddr = kmap_atomic(desc_bh->b_page);
818*4882a593Smuzhiyun 		desc = nilfs_palloc_block_get_group_desc(
819*4882a593Smuzhiyun 			inode, group, desc_bh, desc_kaddr);
820*4882a593Smuzhiyun 		nfree = nilfs_palloc_group_desc_add_entries(desc, lock, n);
821*4882a593Smuzhiyun 		kunmap_atomic(desc_kaddr);
822*4882a593Smuzhiyun 		mark_buffer_dirty(desc_bh);
823*4882a593Smuzhiyun 		nilfs_mdt_mark_dirty(inode);
824*4882a593Smuzhiyun 		brelse(desc_bh);
825*4882a593Smuzhiyun 
826*4882a593Smuzhiyun 		if (nfree == nilfs_palloc_entries_per_group(inode)) {
827*4882a593Smuzhiyun 			ret = nilfs_palloc_delete_bitmap_block(inode, group);
828*4882a593Smuzhiyun 			if (ret && ret != -ENOENT)
829*4882a593Smuzhiyun 				nilfs_warn(inode->i_sb,
830*4882a593Smuzhiyun 					   "error %d deleting bitmap block of group=%lu, ino=%lu",
831*4882a593Smuzhiyun 					   ret, group, inode->i_ino);
832*4882a593Smuzhiyun 		}
833*4882a593Smuzhiyun 	}
834*4882a593Smuzhiyun 	return 0;
835*4882a593Smuzhiyun }
836*4882a593Smuzhiyun 
nilfs_palloc_setup_cache(struct inode * inode,struct nilfs_palloc_cache * cache)837*4882a593Smuzhiyun void nilfs_palloc_setup_cache(struct inode *inode,
838*4882a593Smuzhiyun 			      struct nilfs_palloc_cache *cache)
839*4882a593Smuzhiyun {
840*4882a593Smuzhiyun 	NILFS_MDT(inode)->mi_palloc_cache = cache;
841*4882a593Smuzhiyun 	spin_lock_init(&cache->lock);
842*4882a593Smuzhiyun }
843*4882a593Smuzhiyun 
nilfs_palloc_clear_cache(struct inode * inode)844*4882a593Smuzhiyun void nilfs_palloc_clear_cache(struct inode *inode)
845*4882a593Smuzhiyun {
846*4882a593Smuzhiyun 	struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;
847*4882a593Smuzhiyun 
848*4882a593Smuzhiyun 	spin_lock(&cache->lock);
849*4882a593Smuzhiyun 	brelse(cache->prev_desc.bh);
850*4882a593Smuzhiyun 	brelse(cache->prev_bitmap.bh);
851*4882a593Smuzhiyun 	brelse(cache->prev_entry.bh);
852*4882a593Smuzhiyun 	cache->prev_desc.bh = NULL;
853*4882a593Smuzhiyun 	cache->prev_bitmap.bh = NULL;
854*4882a593Smuzhiyun 	cache->prev_entry.bh = NULL;
855*4882a593Smuzhiyun 	spin_unlock(&cache->lock);
856*4882a593Smuzhiyun }
857*4882a593Smuzhiyun 
nilfs_palloc_destroy_cache(struct inode * inode)858*4882a593Smuzhiyun void nilfs_palloc_destroy_cache(struct inode *inode)
859*4882a593Smuzhiyun {
860*4882a593Smuzhiyun 	nilfs_palloc_clear_cache(inode);
861*4882a593Smuzhiyun 	NILFS_MDT(inode)->mi_palloc_cache = NULL;
862*4882a593Smuzhiyun }
863