blob: eaa0c6af80c3481d02f07ac8fe0d6722df0236ca [file] [log] [blame]
Ryusuke Konishi54426802009-04-06 19:01:29 -07001/*
2 * alloc.c - NILFS dat/inode allocator
3 *
4 * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
Ryusuke Konishi54426802009-04-06 19:01:29 -070016 * Original code was written by Koji Sato <koji@osrg.net>.
17 * Two allocators were unified by Ryusuke Konishi <ryusuke@osrg.net>,
18 * Amagai Yoshiji <amagai@osrg.net>.
19 */
20
21#include <linux/types.h>
22#include <linux/buffer_head.h>
23#include <linux/fs.h>
24#include <linux/bitops.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090025#include <linux/slab.h>
Ryusuke Konishi54426802009-04-06 19:01:29 -070026#include "mdt.h"
27#include "alloc.h"
28
29
Ryusuke Konishidb55d922010-04-12 01:46:02 +090030/**
31 * nilfs_palloc_groups_per_desc_block - get the number of groups that a group
32 * descriptor block can maintain
33 * @inode: inode of metadata file using this allocator
34 */
Ryusuke Konishi54426802009-04-06 19:01:29 -070035static inline unsigned long
36nilfs_palloc_groups_per_desc_block(const struct inode *inode)
37{
38 return (1UL << inode->i_blkbits) /
39 sizeof(struct nilfs_palloc_group_desc);
40}
41
Ryusuke Konishidb55d922010-04-12 01:46:02 +090042/**
43 * nilfs_palloc_groups_count - get maximum number of groups
44 * @inode: inode of metadata file using this allocator
45 */
Ryusuke Konishi54426802009-04-06 19:01:29 -070046static inline unsigned long
47nilfs_palloc_groups_count(const struct inode *inode)
48{
49 return 1UL << (BITS_PER_LONG - (inode->i_blkbits + 3 /* log2(8) */));
50}
51
Ryusuke Konishidb55d922010-04-12 01:46:02 +090052/**
53 * nilfs_palloc_init_blockgroup - initialize private variables for allocator
54 * @inode: inode of metadata file using this allocator
55 * @entry_size: size of the persistent object
56 */
Ryusuke Konishi54426802009-04-06 19:01:29 -070057int nilfs_palloc_init_blockgroup(struct inode *inode, unsigned entry_size)
58{
59 struct nilfs_mdt_info *mi = NILFS_MDT(inode);
60
61 mi->mi_bgl = kmalloc(sizeof(*mi->mi_bgl), GFP_NOFS);
62 if (!mi->mi_bgl)
63 return -ENOMEM;
64
65 bgl_lock_init(mi->mi_bgl);
66
67 nilfs_mdt_set_entry_size(inode, entry_size, 0);
68
69 mi->mi_blocks_per_group =
70 DIV_ROUND_UP(nilfs_palloc_entries_per_group(inode),
71 mi->mi_entries_per_block) + 1;
72 /* Number of blocks in a group including entry blocks and
73 a bitmap block */
74 mi->mi_blocks_per_desc_block =
75 nilfs_palloc_groups_per_desc_block(inode) *
76 mi->mi_blocks_per_group + 1;
77 /* Number of blocks per descriptor including the
78 descriptor block */
79 return 0;
80}
81
Ryusuke Konishidb55d922010-04-12 01:46:02 +090082/**
83 * nilfs_palloc_group - get group number and offset from an entry number
84 * @inode: inode of metadata file using this allocator
85 * @nr: serial number of the entry (e.g. inode number)
86 * @offset: pointer to store offset number in the group
87 */
Ryusuke Konishi54426802009-04-06 19:01:29 -070088static unsigned long nilfs_palloc_group(const struct inode *inode, __u64 nr,
89 unsigned long *offset)
90{
91 __u64 group = nr;
92
93 *offset = do_div(group, nilfs_palloc_entries_per_group(inode));
94 return group;
95}
96
Ryusuke Konishidb55d922010-04-12 01:46:02 +090097/**
98 * nilfs_palloc_desc_blkoff - get block offset of a group descriptor block
99 * @inode: inode of metadata file using this allocator
100 * @group: group number
101 *
102 * nilfs_palloc_desc_blkoff() returns block offset of the descriptor
103 * block which contains a descriptor of the specified group.
104 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700105static unsigned long
106nilfs_palloc_desc_blkoff(const struct inode *inode, unsigned long group)
107{
108 unsigned long desc_block =
109 group / nilfs_palloc_groups_per_desc_block(inode);
110 return desc_block * NILFS_MDT(inode)->mi_blocks_per_desc_block;
111}
112
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900113/**
114 * nilfs_palloc_bitmap_blkoff - get block offset of a bitmap block
115 * @inode: inode of metadata file using this allocator
116 * @group: group number
117 *
118 * nilfs_palloc_bitmap_blkoff() returns block offset of the bitmap
119 * block used to allocate/deallocate entries in the specified group.
120 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700121static unsigned long
122nilfs_palloc_bitmap_blkoff(const struct inode *inode, unsigned long group)
123{
124 unsigned long desc_offset =
125 group % nilfs_palloc_groups_per_desc_block(inode);
126 return nilfs_palloc_desc_blkoff(inode, group) + 1 +
127 desc_offset * NILFS_MDT(inode)->mi_blocks_per_group;
128}
129
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900130/**
131 * nilfs_palloc_group_desc_nfrees - get the number of free entries in a group
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900132 * @desc: pointer to descriptor structure for the group
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800133 * @lock: spin lock protecting @desc
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900134 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700135static unsigned long
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800136nilfs_palloc_group_desc_nfrees(const struct nilfs_palloc_group_desc *desc,
137 spinlock_t *lock)
Ryusuke Konishi54426802009-04-06 19:01:29 -0700138{
139 unsigned long nfree;
140
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800141 spin_lock(lock);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700142 nfree = le32_to_cpu(desc->pg_nfrees);
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800143 spin_unlock(lock);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700144 return nfree;
145}
146
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900147/**
148 * nilfs_palloc_group_desc_add_entries - adjust count of free entries
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900149 * @desc: pointer to descriptor structure for the group
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800150 * @lock: spin lock protecting @desc
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900151 * @n: delta to be added
152 */
Ryusuke Konishid0c14a92015-11-06 16:31:56 -0800153static u32
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800154nilfs_palloc_group_desc_add_entries(struct nilfs_palloc_group_desc *desc,
155 spinlock_t *lock, u32 n)
Ryusuke Konishi54426802009-04-06 19:01:29 -0700156{
Ryusuke Konishid0c14a92015-11-06 16:31:56 -0800157 u32 nfree;
158
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800159 spin_lock(lock);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700160 le32_add_cpu(&desc->pg_nfrees, n);
Ryusuke Konishid0c14a92015-11-06 16:31:56 -0800161 nfree = le32_to_cpu(desc->pg_nfrees);
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800162 spin_unlock(lock);
Ryusuke Konishid0c14a92015-11-06 16:31:56 -0800163 return nfree;
Ryusuke Konishi54426802009-04-06 19:01:29 -0700164}
165
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900166/**
167 * nilfs_palloc_entry_blkoff - get block offset of an entry block
168 * @inode: inode of metadata file using this allocator
169 * @nr: serial number of the entry (e.g. inode number)
170 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700171static unsigned long
172nilfs_palloc_entry_blkoff(const struct inode *inode, __u64 nr)
173{
174 unsigned long group, group_offset;
175
176 group = nilfs_palloc_group(inode, nr, &group_offset);
177
178 return nilfs_palloc_bitmap_blkoff(inode, group) + 1 +
179 group_offset / NILFS_MDT(inode)->mi_entries_per_block;
180}
181
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900182/**
183 * nilfs_palloc_desc_block_init - initialize buffer of a group descriptor block
184 * @inode: inode of metadata file
185 * @bh: buffer head of the buffer to be initialized
186 * @kaddr: kernel address mapped for the page including the buffer
187 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700188static void nilfs_palloc_desc_block_init(struct inode *inode,
189 struct buffer_head *bh, void *kaddr)
190{
191 struct nilfs_palloc_group_desc *desc = kaddr + bh_offset(bh);
192 unsigned long n = nilfs_palloc_groups_per_desc_block(inode);
193 __le32 nfrees;
194
195 nfrees = cpu_to_le32(nilfs_palloc_entries_per_group(inode));
196 while (n-- > 0) {
197 desc->pg_nfrees = nfrees;
198 desc++;
199 }
200}
201
Ryusuke Konishi70622a22009-11-14 18:40:27 +0900202static int nilfs_palloc_get_block(struct inode *inode, unsigned long blkoff,
203 int create,
204 void (*init_block)(struct inode *,
205 struct buffer_head *,
206 void *),
207 struct buffer_head **bhp,
208 struct nilfs_bh_assoc *prev,
209 spinlock_t *lock)
210{
211 int ret;
212
213 spin_lock(lock);
214 if (prev->bh && blkoff == prev->blkoff) {
215 get_bh(prev->bh);
216 *bhp = prev->bh;
217 spin_unlock(lock);
218 return 0;
219 }
220 spin_unlock(lock);
221
222 ret = nilfs_mdt_get_block(inode, blkoff, create, init_block, bhp);
223 if (!ret) {
224 spin_lock(lock);
225 /*
226 * The following code must be safe for change of the
227 * cache contents during the get block call.
228 */
229 brelse(prev->bh);
230 get_bh(*bhp);
231 prev->bh = *bhp;
232 prev->blkoff = blkoff;
233 spin_unlock(lock);
234 }
235 return ret;
236}
237
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900238/**
Ryusuke Konishida019952015-11-06 16:31:54 -0800239 * nilfs_palloc_delete_block - delete a block on the persistent allocator file
240 * @inode: inode of metadata file using this allocator
241 * @blkoff: block offset
242 * @prev: nilfs_bh_assoc struct of the last used buffer
243 * @lock: spin lock protecting @prev
244 */
245static int nilfs_palloc_delete_block(struct inode *inode, unsigned long blkoff,
246 struct nilfs_bh_assoc *prev,
247 spinlock_t *lock)
248{
249 spin_lock(lock);
250 if (prev->bh && blkoff == prev->blkoff) {
251 brelse(prev->bh);
252 prev->bh = NULL;
253 }
254 spin_unlock(lock);
255 return nilfs_mdt_delete_block(inode, blkoff);
256}
257
258/**
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900259 * nilfs_palloc_get_desc_block - get buffer head of a group descriptor block
260 * @inode: inode of metadata file using this allocator
261 * @group: group number
262 * @create: create flag
263 * @bhp: pointer to store the resultant buffer head
264 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700265static int nilfs_palloc_get_desc_block(struct inode *inode,
266 unsigned long group,
267 int create, struct buffer_head **bhp)
268{
Ryusuke Konishi70622a22009-11-14 18:40:27 +0900269 struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;
270
271 return nilfs_palloc_get_block(inode,
272 nilfs_palloc_desc_blkoff(inode, group),
273 create, nilfs_palloc_desc_block_init,
274 bhp, &cache->prev_desc, &cache->lock);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700275}
276
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900277/**
278 * nilfs_palloc_get_bitmap_block - get buffer head of a bitmap block
279 * @inode: inode of metadata file using this allocator
280 * @group: group number
281 * @create: create flag
282 * @bhp: pointer to store the resultant buffer head
283 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700284static int nilfs_palloc_get_bitmap_block(struct inode *inode,
285 unsigned long group,
286 int create, struct buffer_head **bhp)
287{
Ryusuke Konishi70622a22009-11-14 18:40:27 +0900288 struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;
289
290 return nilfs_palloc_get_block(inode,
291 nilfs_palloc_bitmap_blkoff(inode, group),
292 create, NULL, bhp,
293 &cache->prev_bitmap, &cache->lock);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700294}
295
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900296/**
Ryusuke Konishida019952015-11-06 16:31:54 -0800297 * nilfs_palloc_delete_bitmap_block - delete a bitmap block
298 * @inode: inode of metadata file using this allocator
299 * @group: group number
300 */
301static int nilfs_palloc_delete_bitmap_block(struct inode *inode,
302 unsigned long group)
303{
304 struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;
305
306 return nilfs_palloc_delete_block(inode,
307 nilfs_palloc_bitmap_blkoff(inode,
308 group),
309 &cache->prev_bitmap, &cache->lock);
310}
311
312/**
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900313 * nilfs_palloc_get_entry_block - get buffer head of an entry block
314 * @inode: inode of metadata file using this allocator
315 * @nr: serial number of the entry (e.g. inode number)
316 * @create: create flag
317 * @bhp: pointer to store the resultant buffer head
318 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700319int nilfs_palloc_get_entry_block(struct inode *inode, __u64 nr,
320 int create, struct buffer_head **bhp)
321{
Ryusuke Konishi70622a22009-11-14 18:40:27 +0900322 struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;
323
324 return nilfs_palloc_get_block(inode,
325 nilfs_palloc_entry_blkoff(inode, nr),
326 create, NULL, bhp,
327 &cache->prev_entry, &cache->lock);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700328}
329
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900330/**
Ryusuke Konishida019952015-11-06 16:31:54 -0800331 * nilfs_palloc_delete_entry_block - delete an entry block
332 * @inode: inode of metadata file using this allocator
333 * @nr: serial number of the entry
334 */
335static int nilfs_palloc_delete_entry_block(struct inode *inode, __u64 nr)
336{
337 struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;
338
339 return nilfs_palloc_delete_block(inode,
340 nilfs_palloc_entry_blkoff(inode, nr),
341 &cache->prev_entry, &cache->lock);
342}
343
344/**
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900345 * nilfs_palloc_block_get_group_desc - get kernel address of a group descriptor
346 * @inode: inode of metadata file using this allocator
347 * @group: group number
348 * @bh: buffer head of the buffer storing the group descriptor block
349 * @kaddr: kernel address mapped for the page including the buffer
350 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700351static struct nilfs_palloc_group_desc *
352nilfs_palloc_block_get_group_desc(const struct inode *inode,
353 unsigned long group,
354 const struct buffer_head *bh, void *kaddr)
355{
356 return (struct nilfs_palloc_group_desc *)(kaddr + bh_offset(bh)) +
357 group % nilfs_palloc_groups_per_desc_block(inode);
358}
359
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900360/**
361 * nilfs_palloc_block_get_entry - get kernel address of an entry
362 * @inode: inode of metadata file using this allocator
363 * @nr: serial number of the entry (e.g. inode number)
364 * @bh: buffer head of the buffer storing the entry block
365 * @kaddr: kernel address mapped for the page including the buffer
366 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700367void *nilfs_palloc_block_get_entry(const struct inode *inode, __u64 nr,
368 const struct buffer_head *bh, void *kaddr)
369{
370 unsigned long entry_offset, group_offset;
371
372 nilfs_palloc_group(inode, nr, &group_offset);
373 entry_offset = group_offset % NILFS_MDT(inode)->mi_entries_per_block;
374
375 return kaddr + bh_offset(bh) +
376 entry_offset * NILFS_MDT(inode)->mi_entry_size;
377}
378
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900379/**
380 * nilfs_palloc_find_available_slot - find available slot in a group
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900381 * @bitmap: bitmap of the group
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800382 * @target: offset number of an entry in the group (start point)
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900383 * @bsize: size in bits
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800384 * @lock: spin lock protecting @bitmap
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900385 */
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800386static int nilfs_palloc_find_available_slot(unsigned char *bitmap,
Ryusuke Konishi54426802009-04-06 19:01:29 -0700387 unsigned long target,
Ryusuke Konishi18c41b32015-11-06 16:31:48 -0800388 unsigned bsize,
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800389 spinlock_t *lock)
Ryusuke Konishi54426802009-04-06 19:01:29 -0700390{
Ryusuke Konishi18c41b32015-11-06 16:31:48 -0800391 int pos, end = bsize;
Ryusuke Konishi54426802009-04-06 19:01:29 -0700392
Ryusuke Konishi18c41b32015-11-06 16:31:48 -0800393 if (likely(target < bsize)) {
394 pos = target;
395 do {
396 pos = nilfs_find_next_zero_bit(bitmap, end, pos);
397 if (pos >= end)
398 break;
399 if (!nilfs_set_bit_atomic(lock, pos, bitmap))
Ryusuke Konishi54426802009-04-06 19:01:29 -0700400 return pos;
Ryusuke Konishi18c41b32015-11-06 16:31:48 -0800401 } while (++pos < end);
402
403 end = target;
Ryusuke Konishi54426802009-04-06 19:01:29 -0700404 }
Ryusuke Konishi18c41b32015-11-06 16:31:48 -0800405
406 /* wrap around */
407 for (pos = 0; pos < end; pos++) {
408 pos = nilfs_find_next_zero_bit(bitmap, end, pos);
409 if (pos >= end)
410 break;
411 if (!nilfs_set_bit_atomic(lock, pos, bitmap))
412 return pos;
413 }
414
Ryusuke Konishi54426802009-04-06 19:01:29 -0700415 return -ENOSPC;
416}
417
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900418/**
419 * nilfs_palloc_rest_groups_in_desc_block - get the remaining number of groups
420 * in a group descriptor block
421 * @inode: inode of metadata file using this allocator
422 * @curr: current group number
423 * @max: maximum number of groups
424 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700425static unsigned long
426nilfs_palloc_rest_groups_in_desc_block(const struct inode *inode,
427 unsigned long curr, unsigned long max)
428{
429 return min_t(unsigned long,
430 nilfs_palloc_groups_per_desc_block(inode) -
431 curr % nilfs_palloc_groups_per_desc_block(inode),
432 max - curr + 1);
433}
434
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900435/**
Vyacheslav Dubeykoc7ef9722013-07-03 15:08:05 -0700436 * nilfs_palloc_count_desc_blocks - count descriptor blocks number
437 * @inode: inode of metadata file using this allocator
438 * @desc_blocks: descriptor blocks number [out]
439 */
440static int nilfs_palloc_count_desc_blocks(struct inode *inode,
441 unsigned long *desc_blocks)
442{
Ryusuke Konishi3568a132015-04-16 12:46:34 -0700443 __u64 blknum;
Vyacheslav Dubeykoc7ef9722013-07-03 15:08:05 -0700444 int ret;
445
446 ret = nilfs_bmap_last_key(NILFS_I(inode)->i_bmap, &blknum);
447 if (likely(!ret))
448 *desc_blocks = DIV_ROUND_UP(
Ryusuke Konishi3568a132015-04-16 12:46:34 -0700449 (unsigned long)blknum,
450 NILFS_MDT(inode)->mi_blocks_per_desc_block);
Vyacheslav Dubeykoc7ef9722013-07-03 15:08:05 -0700451 return ret;
452}
453
454/**
455 * nilfs_palloc_mdt_file_can_grow - check potential opportunity for
456 * MDT file growing
457 * @inode: inode of metadata file using this allocator
458 * @desc_blocks: known current descriptor blocks count
459 */
460static inline bool nilfs_palloc_mdt_file_can_grow(struct inode *inode,
461 unsigned long desc_blocks)
462{
463 return (nilfs_palloc_groups_per_desc_block(inode) * desc_blocks) <
464 nilfs_palloc_groups_count(inode);
465}
466
467/**
468 * nilfs_palloc_count_max_entries - count max number of entries that can be
469 * described by descriptor blocks count
470 * @inode: inode of metadata file using this allocator
471 * @nused: current number of used entries
472 * @nmaxp: max number of entries [out]
473 */
474int nilfs_palloc_count_max_entries(struct inode *inode, u64 nused, u64 *nmaxp)
475{
476 unsigned long desc_blocks = 0;
477 u64 entries_per_desc_block, nmax;
478 int err;
479
480 err = nilfs_palloc_count_desc_blocks(inode, &desc_blocks);
481 if (unlikely(err))
482 return err;
483
484 entries_per_desc_block = (u64)nilfs_palloc_entries_per_group(inode) *
485 nilfs_palloc_groups_per_desc_block(inode);
486 nmax = entries_per_desc_block * desc_blocks;
487
488 if (nused == nmax &&
489 nilfs_palloc_mdt_file_can_grow(inode, desc_blocks))
490 nmax += entries_per_desc_block;
491
492 if (nused > nmax)
493 return -ERANGE;
494
495 *nmaxp = nmax;
496 return 0;
497}
498
499/**
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900500 * nilfs_palloc_prepare_alloc_entry - prepare to allocate a persistent object
501 * @inode: inode of metadata file using this allocator
502 * @req: nilfs_palloc_req structure exchanged for the allocation
503 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700504int nilfs_palloc_prepare_alloc_entry(struct inode *inode,
505 struct nilfs_palloc_req *req)
506{
507 struct buffer_head *desc_bh, *bitmap_bh;
508 struct nilfs_palloc_group_desc *desc;
509 unsigned char *bitmap;
510 void *desc_kaddr, *bitmap_kaddr;
511 unsigned long group, maxgroup, ngroups;
512 unsigned long group_offset, maxgroup_offset;
Ryusuke Konishi09ef29e2015-11-06 16:32:14 -0800513 unsigned long n, entries_per_group;
Ryusuke Konishi54426802009-04-06 19:01:29 -0700514 unsigned long i, j;
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800515 spinlock_t *lock;
Ryusuke Konishi54426802009-04-06 19:01:29 -0700516 int pos, ret;
517
518 ngroups = nilfs_palloc_groups_count(inode);
519 maxgroup = ngroups - 1;
520 group = nilfs_palloc_group(inode, req->pr_entry_nr, &group_offset);
521 entries_per_group = nilfs_palloc_entries_per_group(inode);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700522
523 for (i = 0; i < ngroups; i += n) {
524 if (group >= ngroups) {
525 /* wrap around */
526 group = 0;
527 maxgroup = nilfs_palloc_group(inode, req->pr_entry_nr,
528 &maxgroup_offset) - 1;
529 }
530 ret = nilfs_palloc_get_desc_block(inode, group, 1, &desc_bh);
531 if (ret < 0)
532 return ret;
533 desc_kaddr = kmap(desc_bh->b_page);
534 desc = nilfs_palloc_block_get_group_desc(
535 inode, group, desc_bh, desc_kaddr);
536 n = nilfs_palloc_rest_groups_in_desc_block(inode, group,
537 maxgroup);
538 for (j = 0; j < n; j++, desc++, group++) {
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800539 lock = nilfs_mdt_bgl_lock(inode, group);
540 if (nilfs_palloc_group_desc_nfrees(desc, lock) > 0) {
Ryusuke Konishi54426802009-04-06 19:01:29 -0700541 ret = nilfs_palloc_get_bitmap_block(
542 inode, group, 1, &bitmap_bh);
543 if (ret < 0)
544 goto out_desc;
545 bitmap_kaddr = kmap(bitmap_bh->b_page);
Ryusuke Konishi141bbdb2009-11-14 13:48:06 +0900546 bitmap = bitmap_kaddr + bh_offset(bitmap_bh);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700547 pos = nilfs_palloc_find_available_slot(
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800548 bitmap, group_offset,
549 entries_per_group, lock);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700550 if (pos >= 0) {
551 /* found a free entry */
552 nilfs_palloc_group_desc_add_entries(
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800553 desc, lock, -1);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700554 req->pr_entry_nr =
555 entries_per_group * group + pos;
556 kunmap(desc_bh->b_page);
557 kunmap(bitmap_bh->b_page);
558
559 req->pr_desc_bh = desc_bh;
560 req->pr_bitmap_bh = bitmap_bh;
561 return 0;
562 }
563 kunmap(bitmap_bh->b_page);
564 brelse(bitmap_bh);
565 }
566
567 group_offset = 0;
568 }
569
570 kunmap(desc_bh->b_page);
571 brelse(desc_bh);
572 }
573
574 /* no entries left */
575 return -ENOSPC;
576
577 out_desc:
578 kunmap(desc_bh->b_page);
579 brelse(desc_bh);
580 return ret;
581}
582
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900583/**
584 * nilfs_palloc_commit_alloc_entry - finish allocation of a persistent object
585 * @inode: inode of metadata file using this allocator
586 * @req: nilfs_palloc_req structure exchanged for the allocation
587 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700588void nilfs_palloc_commit_alloc_entry(struct inode *inode,
589 struct nilfs_palloc_req *req)
590{
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +0900591 mark_buffer_dirty(req->pr_bitmap_bh);
592 mark_buffer_dirty(req->pr_desc_bh);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700593 nilfs_mdt_mark_dirty(inode);
594
595 brelse(req->pr_bitmap_bh);
596 brelse(req->pr_desc_bh);
597}
598
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900599/**
600 * nilfs_palloc_commit_free_entry - finish deallocating a persistent object
601 * @inode: inode of metadata file using this allocator
602 * @req: nilfs_palloc_req structure exchanged for the removal
603 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700604void nilfs_palloc_commit_free_entry(struct inode *inode,
605 struct nilfs_palloc_req *req)
606{
607 struct nilfs_palloc_group_desc *desc;
608 unsigned long group, group_offset;
609 unsigned char *bitmap;
610 void *desc_kaddr, *bitmap_kaddr;
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800611 spinlock_t *lock;
Ryusuke Konishi54426802009-04-06 19:01:29 -0700612
613 group = nilfs_palloc_group(inode, req->pr_entry_nr, &group_offset);
614 desc_kaddr = kmap(req->pr_desc_bh->b_page);
615 desc = nilfs_palloc_block_get_group_desc(inode, group,
616 req->pr_desc_bh, desc_kaddr);
617 bitmap_kaddr = kmap(req->pr_bitmap_bh->b_page);
Ryusuke Konishi141bbdb2009-11-14 13:48:06 +0900618 bitmap = bitmap_kaddr + bh_offset(req->pr_bitmap_bh);
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800619 lock = nilfs_mdt_bgl_lock(inode, group);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700620
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800621 if (!nilfs_clear_bit_atomic(lock, group_offset, bitmap))
Ryusuke Konishib7bed712015-11-06 16:31:43 -0800622 nilfs_warning(inode->i_sb, __func__,
623 "entry number %llu already freed: ino=%lu\n",
624 (unsigned long long)req->pr_entry_nr,
625 (unsigned long)inode->i_ino);
Ryusuke Konishi9954e7a2011-02-23 02:26:17 +0900626 else
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800627 nilfs_palloc_group_desc_add_entries(desc, lock, 1);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700628
629 kunmap(req->pr_bitmap_bh->b_page);
630 kunmap(req->pr_desc_bh->b_page);
631
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +0900632 mark_buffer_dirty(req->pr_desc_bh);
633 mark_buffer_dirty(req->pr_bitmap_bh);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700634 nilfs_mdt_mark_dirty(inode);
635
636 brelse(req->pr_bitmap_bh);
637 brelse(req->pr_desc_bh);
638}
639
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900640/**
641 * nilfs_palloc_abort_alloc_entry - cancel allocation of a persistent object
642 * @inode: inode of metadata file using this allocator
643 * @req: nilfs_palloc_req structure exchanged for the allocation
644 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700645void nilfs_palloc_abort_alloc_entry(struct inode *inode,
646 struct nilfs_palloc_req *req)
647{
648 struct nilfs_palloc_group_desc *desc;
649 void *desc_kaddr, *bitmap_kaddr;
650 unsigned char *bitmap;
651 unsigned long group, group_offset;
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800652 spinlock_t *lock;
Ryusuke Konishi54426802009-04-06 19:01:29 -0700653
654 group = nilfs_palloc_group(inode, req->pr_entry_nr, &group_offset);
655 desc_kaddr = kmap(req->pr_desc_bh->b_page);
656 desc = nilfs_palloc_block_get_group_desc(inode, group,
657 req->pr_desc_bh, desc_kaddr);
658 bitmap_kaddr = kmap(req->pr_bitmap_bh->b_page);
Ryusuke Konishi141bbdb2009-11-14 13:48:06 +0900659 bitmap = bitmap_kaddr + bh_offset(req->pr_bitmap_bh);
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800660 lock = nilfs_mdt_bgl_lock(inode, group);
661
662 if (!nilfs_clear_bit_atomic(lock, group_offset, bitmap))
Ryusuke Konishib7bed712015-11-06 16:31:43 -0800663 nilfs_warning(inode->i_sb, __func__,
664 "entry number %llu already freed: ino=%lu\n",
665 (unsigned long long)req->pr_entry_nr,
666 (unsigned long)inode->i_ino);
Ryusuke Konishi9954e7a2011-02-23 02:26:17 +0900667 else
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800668 nilfs_palloc_group_desc_add_entries(desc, lock, 1);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700669
670 kunmap(req->pr_bitmap_bh->b_page);
671 kunmap(req->pr_desc_bh->b_page);
672
673 brelse(req->pr_bitmap_bh);
674 brelse(req->pr_desc_bh);
675
676 req->pr_entry_nr = 0;
677 req->pr_bitmap_bh = NULL;
678 req->pr_desc_bh = NULL;
679}
680
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900681/**
682 * nilfs_palloc_prepare_free_entry - prepare to deallocate a persistent object
683 * @inode: inode of metadata file using this allocator
684 * @req: nilfs_palloc_req structure exchanged for the removal
685 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700686int nilfs_palloc_prepare_free_entry(struct inode *inode,
687 struct nilfs_palloc_req *req)
688{
689 struct buffer_head *desc_bh, *bitmap_bh;
690 unsigned long group, group_offset;
691 int ret;
692
693 group = nilfs_palloc_group(inode, req->pr_entry_nr, &group_offset);
694 ret = nilfs_palloc_get_desc_block(inode, group, 1, &desc_bh);
695 if (ret < 0)
696 return ret;
697 ret = nilfs_palloc_get_bitmap_block(inode, group, 1, &bitmap_bh);
698 if (ret < 0) {
699 brelse(desc_bh);
700 return ret;
701 }
702
703 req->pr_desc_bh = desc_bh;
704 req->pr_bitmap_bh = bitmap_bh;
705 return 0;
706}
707
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900708/**
709 * nilfs_palloc_abort_free_entry - cancel deallocating a persistent object
710 * @inode: inode of metadata file using this allocator
711 * @req: nilfs_palloc_req structure exchanged for the removal
712 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700713void nilfs_palloc_abort_free_entry(struct inode *inode,
714 struct nilfs_palloc_req *req)
715{
716 brelse(req->pr_bitmap_bh);
717 brelse(req->pr_desc_bh);
718
719 req->pr_entry_nr = 0;
720 req->pr_bitmap_bh = NULL;
721 req->pr_desc_bh = NULL;
722}
723
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900724/**
Ryusuke Konishidb55d922010-04-12 01:46:02 +0900725 * nilfs_palloc_freev - deallocate a set of persistent objects
726 * @inode: inode of metadata file using this allocator
727 * @entry_nrs: array of entry numbers to be deallocated
728 * @nitems: number of entries stored in @entry_nrs
729 */
Ryusuke Konishi54426802009-04-06 19:01:29 -0700730int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems)
731{
732 struct buffer_head *desc_bh, *bitmap_bh;
733 struct nilfs_palloc_group_desc *desc;
734 unsigned char *bitmap;
735 void *desc_kaddr, *bitmap_kaddr;
736 unsigned long group, group_offset;
Ryusuke Konishid0c14a92015-11-06 16:31:56 -0800737 __u64 group_min_nr, last_nrs[8];
Ryusuke Konishib2258092015-11-06 16:31:51 -0800738 const unsigned long epg = nilfs_palloc_entries_per_group(inode);
Ryusuke Konishid0c14a92015-11-06 16:31:56 -0800739 const unsigned epb = NILFS_MDT(inode)->mi_entries_per_block;
740 unsigned entry_start, end, pos;
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800741 spinlock_t *lock;
Ryusuke Konishid0c14a92015-11-06 16:31:56 -0800742 int i, j, k, ret;
743 u32 nfree;
Ryusuke Konishi54426802009-04-06 19:01:29 -0700744
Ryusuke Konishi349dbc32011-05-10 20:59:34 +0900745 for (i = 0; i < nitems; i = j) {
Ryusuke Konishid0c14a92015-11-06 16:31:56 -0800746 int change_group = false;
747 int nempties = 0, n = 0;
748
Ryusuke Konishi54426802009-04-06 19:01:29 -0700749 group = nilfs_palloc_group(inode, entry_nrs[i], &group_offset);
750 ret = nilfs_palloc_get_desc_block(inode, group, 0, &desc_bh);
751 if (ret < 0)
752 return ret;
753 ret = nilfs_palloc_get_bitmap_block(inode, group, 0,
754 &bitmap_bh);
755 if (ret < 0) {
756 brelse(desc_bh);
757 return ret;
758 }
Ryusuke Konishib2258092015-11-06 16:31:51 -0800759
760 /* Get the first entry number of the group */
761 group_min_nr = (__u64)group * epg;
762
Ryusuke Konishi54426802009-04-06 19:01:29 -0700763 bitmap_kaddr = kmap(bitmap_bh->b_page);
Ryusuke Konishi141bbdb2009-11-14 13:48:06 +0900764 bitmap = bitmap_kaddr + bh_offset(bitmap_bh);
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800765 lock = nilfs_mdt_bgl_lock(inode, group);
Ryusuke Konishid0c14a92015-11-06 16:31:56 -0800766
767 j = i;
768 entry_start = rounddown(group_offset, epb);
769 do {
Ryusuke Konishi4e9e63a2015-11-06 16:31:45 -0800770 if (!nilfs_clear_bit_atomic(lock, group_offset,
771 bitmap)) {
Ryusuke Konishib7bed712015-11-06 16:31:43 -0800772 nilfs_warning(inode->i_sb, __func__,
773 "entry number %llu already freed: ino=%lu\n",
774 (unsigned long long)entry_nrs[j],
775 (unsigned long)inode->i_ino);
Ryusuke Konishi9954e7a2011-02-23 02:26:17 +0900776 } else {
777 n++;
Ryusuke Konishi54426802009-04-06 19:01:29 -0700778 }
Ryusuke Konishid0c14a92015-11-06 16:31:56 -0800779
780 j++;
781 if (j >= nitems || entry_nrs[j] < group_min_nr ||
782 entry_nrs[j] >= group_min_nr + epg) {
783 change_group = true;
784 } else {
785 group_offset = entry_nrs[j] - group_min_nr;
786 if (group_offset >= entry_start &&
787 group_offset < entry_start + epb) {
788 /* This entry is in the same block */
789 continue;
790 }
791 }
792
793 /* Test if the entry block is empty or not */
794 end = entry_start + epb;
795 pos = nilfs_find_next_bit(bitmap, end, entry_start);
796 if (pos >= end) {
797 last_nrs[nempties++] = entry_nrs[j - 1];
798 if (nempties >= ARRAY_SIZE(last_nrs))
799 break;
800 }
801
802 if (change_group)
803 break;
804
805 /* Go on to the next entry block */
806 entry_start = rounddown(group_offset, epb);
807 } while (true);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700808
809 kunmap(bitmap_bh->b_page);
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +0900810 mark_buffer_dirty(bitmap_bh);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700811 brelse(bitmap_bh);
Ryusuke Konishid0c14a92015-11-06 16:31:56 -0800812
813 for (k = 0; k < nempties; k++) {
814 ret = nilfs_palloc_delete_entry_block(inode,
815 last_nrs[k]);
816 if (ret && ret != -ENOENT) {
817 nilfs_warning(inode->i_sb, __func__,
818 "failed to delete block of entry %llu: ino=%lu, err=%d\n",
819 (unsigned long long)last_nrs[k],
820 (unsigned long)inode->i_ino, ret);
821 }
822 }
823
824 desc_kaddr = kmap_atomic(desc_bh->b_page);
825 desc = nilfs_palloc_block_get_group_desc(
826 inode, group, desc_bh, desc_kaddr);
827 nfree = nilfs_palloc_group_desc_add_entries(desc, lock, n);
828 kunmap_atomic(desc_kaddr);
829 mark_buffer_dirty(desc_bh);
830 nilfs_mdt_mark_dirty(inode);
Ryusuke Konishi54426802009-04-06 19:01:29 -0700831 brelse(desc_bh);
Ryusuke Konishid0c14a92015-11-06 16:31:56 -0800832
833 if (nfree == nilfs_palloc_entries_per_group(inode)) {
834 ret = nilfs_palloc_delete_bitmap_block(inode, group);
835 if (ret && ret != -ENOENT) {
836 nilfs_warning(inode->i_sb, __func__,
837 "failed to delete bitmap block of group %lu: ino=%lu, err=%d\n",
838 group,
839 (unsigned long)inode->i_ino, ret);
840 }
841 }
Ryusuke Konishi54426802009-04-06 19:01:29 -0700842 }
843 return 0;
844}
Ryusuke Konishidb38d5a2009-11-14 15:54:27 +0900845
846void nilfs_palloc_setup_cache(struct inode *inode,
847 struct nilfs_palloc_cache *cache)
848{
849 NILFS_MDT(inode)->mi_palloc_cache = cache;
850 spin_lock_init(&cache->lock);
851}
852
853void nilfs_palloc_clear_cache(struct inode *inode)
854{
855 struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;
856
857 spin_lock(&cache->lock);
858 brelse(cache->prev_desc.bh);
859 brelse(cache->prev_bitmap.bh);
860 brelse(cache->prev_entry.bh);
861 cache->prev_desc.bh = NULL;
862 cache->prev_bitmap.bh = NULL;
863 cache->prev_entry.bh = NULL;
864 spin_unlock(&cache->lock);
865}
866
867void nilfs_palloc_destroy_cache(struct inode *inode)
868{
869 nilfs_palloc_clear_cache(inode);
870 NILFS_MDT(inode)->mi_palloc_cache = NULL;
871}