blob: 9980d7dbab9122c352b500bf813264a061f45b51 [file] [log] [blame]
Koji Satobdb265e2009-04-06 19:01:23 -07001/*
2 * bmap.h - NILFS block mapping.
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 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 * Written by Koji Sato <koji@osrg.net>.
21 */
22
23#ifndef _NILFS_BMAP_H
24#define _NILFS_BMAP_H
25
26#include <linux/types.h>
27#include <linux/fs.h>
28#include <linux/buffer_head.h>
29#include <linux/nilfs2_fs.h>
30#include "alloc.h"
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +090031#include "dat.h"
Koji Satobdb265e2009-04-06 19:01:23 -070032
33#define NILFS_BMAP_INVALID_PTR 0
34
35#define nilfs_bmap_dkey_to_key(dkey) le64_to_cpu(dkey)
36#define nilfs_bmap_key_to_dkey(key) cpu_to_le64(key)
37#define nilfs_bmap_dptr_to_ptr(dptr) le64_to_cpu(dptr)
38#define nilfs_bmap_ptr_to_dptr(ptr) cpu_to_le64(ptr)
39
40#define nilfs_bmap_keydiff_abs(diff) ((diff) < 0 ? -(diff) : (diff))
41
42
43struct nilfs_bmap;
44
45/**
46 * union nilfs_bmap_ptr_req - request for bmap ptr
47 * @bpr_ptr: bmap pointer
48 * @bpr_req: request for persistent allocator
49 */
50union nilfs_bmap_ptr_req {
51 __u64 bpr_ptr;
52 struct nilfs_palloc_req bpr_req;
53};
54
55/**
56 * struct nilfs_bmap_stats - bmap statistics
57 * @bs_nblocks: number of blocks created or deleted
58 */
59struct nilfs_bmap_stats {
60 unsigned int bs_nblocks;
61};
62
63/**
64 * struct nilfs_bmap_operations - bmap operation table
65 */
66struct nilfs_bmap_operations {
67 int (*bop_lookup)(const struct nilfs_bmap *, __u64, int, __u64 *);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +090068 int (*bop_lookup_contig)(const struct nilfs_bmap *, __u64, __u64 *,
69 unsigned);
Koji Satobdb265e2009-04-06 19:01:23 -070070 int (*bop_insert)(struct nilfs_bmap *, __u64, __u64);
71 int (*bop_delete)(struct nilfs_bmap *, __u64);
72 void (*bop_clear)(struct nilfs_bmap *);
73
74 int (*bop_propagate)(const struct nilfs_bmap *, struct buffer_head *);
75 void (*bop_lookup_dirty_buffers)(struct nilfs_bmap *,
76 struct list_head *);
77
78 int (*bop_assign)(struct nilfs_bmap *,
79 struct buffer_head **,
80 sector_t,
81 union nilfs_binfo *);
82 int (*bop_mark)(struct nilfs_bmap *, __u64, int);
83
84 /* The following functions are internal use only. */
85 int (*bop_last_key)(const struct nilfs_bmap *, __u64 *);
86 int (*bop_check_insert)(const struct nilfs_bmap *, __u64);
87 int (*bop_check_delete)(struct nilfs_bmap *, __u64);
88 int (*bop_gather_data)(struct nilfs_bmap *, __u64 *, __u64 *, int);
89};
90
91
Koji Satobdb265e2009-04-06 19:01:23 -070092#define NILFS_BMAP_SIZE (NILFS_INODE_BMAP_SIZE * sizeof(__le64))
93#define NILFS_BMAP_KEY_BIT (sizeof(unsigned long) * 8 /* CHAR_BIT */)
94#define NILFS_BMAP_NEW_PTR_INIT \
95 (1UL << (sizeof(unsigned long) * 8 /* CHAR_BIT */ - 1))
96
97static inline int nilfs_bmap_is_new_ptr(unsigned long ptr)
98{
99 return !!(ptr & NILFS_BMAP_NEW_PTR_INIT);
100}
101
102
103/**
104 * struct nilfs_bmap - bmap structure
105 * @b_u: raw data
106 * @b_sem: semaphore
107 * @b_inode: owner of bmap
108 * @b_ops: bmap operation table
Koji Satobdb265e2009-04-06 19:01:23 -0700109 * @b_last_allocated_key: last allocated key for data block
110 * @b_last_allocated_ptr: last allocated ptr for data block
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900111 * @b_ptr_type: pointer type
Koji Satobdb265e2009-04-06 19:01:23 -0700112 * @b_state: state
113 */
114struct nilfs_bmap {
115 union {
116 __u8 u_flags;
117 __le64 u_data[NILFS_BMAP_SIZE / sizeof(__le64)];
118 } b_u;
119 struct rw_semaphore b_sem;
120 struct inode *b_inode;
121 const struct nilfs_bmap_operations *b_ops;
Koji Satobdb265e2009-04-06 19:01:23 -0700122 __u64 b_last_allocated_key;
123 __u64 b_last_allocated_ptr;
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900124 int b_ptr_type;
Koji Satobdb265e2009-04-06 19:01:23 -0700125 int b_state;
126};
127
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900128/* pointer type */
129#define NILFS_BMAP_PTR_P 0 /* physical block number (i.e. LBN) */
130#define NILFS_BMAP_PTR_VS 1 /* virtual block number (single
131 version) */
132#define NILFS_BMAP_PTR_VM 2 /* virtual block number (has multiple
133 versions) */
134#define NILFS_BMAP_PTR_U (-1) /* never perform pointer operations */
135
136#define NILFS_BMAP_USE_VBN(bmap) ((bmap)->b_ptr_type > 0)
137
Koji Satobdb265e2009-04-06 19:01:23 -0700138/* state */
139#define NILFS_BMAP_DIRTY 0x00000001
140
141
142int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *);
143int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *);
144void nilfs_bmap_write(struct nilfs_bmap *, struct nilfs_inode *);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900145int nilfs_bmap_lookup_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned);
Koji Satobdb265e2009-04-06 19:01:23 -0700146int nilfs_bmap_insert(struct nilfs_bmap *, unsigned long, unsigned long);
147int nilfs_bmap_delete(struct nilfs_bmap *, unsigned long);
148int nilfs_bmap_last_key(struct nilfs_bmap *, unsigned long *);
149int nilfs_bmap_truncate(struct nilfs_bmap *, unsigned long);
150void nilfs_bmap_clear(struct nilfs_bmap *);
151int nilfs_bmap_propagate(struct nilfs_bmap *, struct buffer_head *);
152void nilfs_bmap_lookup_dirty_buffers(struct nilfs_bmap *, struct list_head *);
153int nilfs_bmap_assign(struct nilfs_bmap *, struct buffer_head **,
154 unsigned long, union nilfs_binfo *);
155int nilfs_bmap_lookup_at_level(struct nilfs_bmap *, __u64, int, __u64 *);
156int nilfs_bmap_mark(struct nilfs_bmap *, __u64, int);
157
158void nilfs_bmap_init_gc(struct nilfs_bmap *);
159void nilfs_bmap_init_gcdat(struct nilfs_bmap *, struct nilfs_bmap *);
160void nilfs_bmap_commit_gcdat(struct nilfs_bmap *, struct nilfs_bmap *);
161
162
Ryusuke Konishi0f3fe332009-08-15 02:29:28 +0900163static inline int nilfs_bmap_lookup(struct nilfs_bmap *bmap, __u64 key,
164 __u64 *ptr)
165{
166 return nilfs_bmap_lookup_at_level(bmap, key, 1, ptr);
167}
168
Koji Satobdb265e2009-04-06 19:01:23 -0700169/*
170 * Internal use only
171 */
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900172struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *);
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900173
174static inline int nilfs_bmap_prepare_alloc_ptr(struct nilfs_bmap *bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900175 union nilfs_bmap_ptr_req *req,
176 struct inode *dat)
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900177{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900178 if (dat)
179 return nilfs_dat_prepare_alloc(dat, &req->bpr_req);
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900180 /* ignore target ptr */
181 req->bpr_ptr = bmap->b_last_allocated_ptr++;
182 return 0;
183}
184
185static inline void nilfs_bmap_commit_alloc_ptr(struct nilfs_bmap *bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900186 union nilfs_bmap_ptr_req *req,
187 struct inode *dat)
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900188{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900189 if (dat)
190 nilfs_dat_commit_alloc(dat, &req->bpr_req);
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900191}
192
193static inline void nilfs_bmap_abort_alloc_ptr(struct nilfs_bmap *bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900194 union nilfs_bmap_ptr_req *req,
195 struct inode *dat)
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900196{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900197 if (dat)
198 nilfs_dat_abort_alloc(dat, &req->bpr_req);
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900199 else
200 bmap->b_last_allocated_ptr--;
201}
202
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900203static inline int nilfs_bmap_prepare_end_ptr(struct nilfs_bmap *bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900204 union nilfs_bmap_ptr_req *req,
205 struct inode *dat)
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900206{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900207 return dat ? nilfs_dat_prepare_end(dat, &req->bpr_req) : 0;
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900208}
209
210static inline void nilfs_bmap_commit_end_ptr(struct nilfs_bmap *bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900211 union nilfs_bmap_ptr_req *req,
212 struct inode *dat)
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900213{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900214 if (dat)
215 nilfs_dat_commit_end(dat, &req->bpr_req,
216 bmap->b_ptr_type == NILFS_BMAP_PTR_VS);
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900217}
218
219static inline void nilfs_bmap_abort_end_ptr(struct nilfs_bmap *bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900220 union nilfs_bmap_ptr_req *req,
221 struct inode *dat)
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900222{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900223 if (dat)
224 nilfs_dat_abort_end(dat, &req->bpr_req);
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900225}
Koji Satobdb265e2009-04-06 19:01:23 -0700226
Koji Satobdb265e2009-04-06 19:01:23 -0700227__u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *,
228 const struct buffer_head *);
229
230__u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *, __u64);
231__u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *);
232
Koji Satobdb265e2009-04-06 19:01:23 -0700233void nilfs_bmap_add_blocks(const struct nilfs_bmap *, int);
234void nilfs_bmap_sub_blocks(const struct nilfs_bmap *, int);
235
236
Koji Satobdb265e2009-04-06 19:01:23 -0700237/* Assume that bmap semaphore is locked. */
238static inline int nilfs_bmap_dirty(const struct nilfs_bmap *bmap)
239{
240 return !!(bmap->b_state & NILFS_BMAP_DIRTY);
241}
242
243/* Assume that bmap semaphore is locked. */
244static inline void nilfs_bmap_set_dirty(struct nilfs_bmap *bmap)
245{
246 bmap->b_state |= NILFS_BMAP_DIRTY;
247}
248
249/* Assume that bmap semaphore is locked. */
250static inline void nilfs_bmap_clear_dirty(struct nilfs_bmap *bmap)
251{
252 bmap->b_state &= ~NILFS_BMAP_DIRTY;
253}
254
255
256#define NILFS_BMAP_LARGE 0x1
257
258#define NILFS_BMAP_SMALL_LOW NILFS_DIRECT_KEY_MIN
259#define NILFS_BMAP_SMALL_HIGH NILFS_DIRECT_KEY_MAX
260#define NILFS_BMAP_LARGE_LOW NILFS_BTREE_ROOT_NCHILDREN_MAX
261#define NILFS_BMAP_LARGE_HIGH NILFS_BTREE_KEY_MAX
262
263#endif /* _NILFS_BMAP_H */