blob: 51824c764294a086fe0467f59ad44623361fb005 [file] [log] [blame]
Koji Satobdb265e2009-04-06 19:01:23 -07001/*
2 * bmap.c - 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#include <linux/fs.h>
24#include <linux/string.h>
25#include <linux/errno.h>
26#include "nilfs.h"
27#include "bmap.h"
28#include "sb.h"
29#include "btnode.h"
30#include "mdt.h"
31#include "dat.h"
32#include "alloc.h"
33
Ryusuke Konishid4b96152009-05-24 03:25:44 +090034static struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap)
35{
36 return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode));
37}
38
Koji Satobdb265e2009-04-06 19:01:23 -070039int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level,
40 __u64 *ptrp)
41{
Ryusuke Konishid4b96152009-05-24 03:25:44 +090042 sector_t blocknr;
Koji Satobdb265e2009-04-06 19:01:23 -070043 int ret;
44
45 down_read(&bmap->b_sem);
Pekka Enberg8acfbf02009-04-06 19:01:49 -070046 ret = bmap->b_ops->bop_lookup(bmap, key, level, ptrp);
Koji Satobdb265e2009-04-06 19:01:23 -070047 if (ret < 0)
48 goto out;
Ryusuke Konishid4b96152009-05-24 03:25:44 +090049 if (NILFS_BMAP_USE_VBN(bmap)) {
50 ret = nilfs_dat_translate(nilfs_bmap_get_dat(bmap), *ptrp,
51 &blocknr);
52 if (!ret)
53 *ptrp = blocknr;
Koji Satobdb265e2009-04-06 19:01:23 -070054 }
55
56 out:
57 up_read(&bmap->b_sem);
58 return ret;
59}
60
61
62/**
63 * nilfs_bmap_lookup - find a record
64 * @bmap: bmap
65 * @key: key
66 * @recp: pointer to record
67 *
68 * Description: nilfs_bmap_lookup() finds a record whose key matches @key in
69 * @bmap.
70 *
71 * Return Value: On success, 0 is returned and the record associated with @key
72 * is stored in the place pointed by @recp. On error, one of the following
73 * negative error codes is returned.
74 *
75 * %-EIO - I/O error.
76 *
77 * %-ENOMEM - Insufficient amount of memory available.
78 *
79 * %-ENOENT - A record associated with @key does not exist.
80 */
81int nilfs_bmap_lookup(struct nilfs_bmap *bmap,
82 unsigned long key,
83 unsigned long *recp)
84{
85 __u64 ptr;
86 int ret;
87
88 /* XXX: use macro for level 1 */
89 ret = nilfs_bmap_lookup_at_level(bmap, key, 1, &ptr);
90 if (recp != NULL)
91 *recp = ptr;
92 return ret;
93}
94
95static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
96{
97 __u64 keys[NILFS_BMAP_SMALL_HIGH + 1];
98 __u64 ptrs[NILFS_BMAP_SMALL_HIGH + 1];
99 int ret, n;
100
101 if (bmap->b_ops->bop_check_insert != NULL) {
Pekka Enberg8acfbf02009-04-06 19:01:49 -0700102 ret = bmap->b_ops->bop_check_insert(bmap, key);
Koji Satobdb265e2009-04-06 19:01:23 -0700103 if (ret > 0) {
Pekka Enberg8acfbf02009-04-06 19:01:49 -0700104 n = bmap->b_ops->bop_gather_data(
Koji Satobdb265e2009-04-06 19:01:23 -0700105 bmap, keys, ptrs, NILFS_BMAP_SMALL_HIGH + 1);
106 if (n < 0)
107 return n;
108 ret = nilfs_btree_convert_and_insert(
Ryusuke Konishi30333422009-05-24 00:09:44 +0900109 bmap, key, ptr, keys, ptrs, n);
Koji Satobdb265e2009-04-06 19:01:23 -0700110 if (ret == 0)
111 bmap->b_u.u_flags |= NILFS_BMAP_LARGE;
112
113 return ret;
114 } else if (ret < 0)
115 return ret;
116 }
117
Pekka Enberg8acfbf02009-04-06 19:01:49 -0700118 return bmap->b_ops->bop_insert(bmap, key, ptr);
Koji Satobdb265e2009-04-06 19:01:23 -0700119}
120
121/**
122 * nilfs_bmap_insert - insert a new key-record pair into a bmap
123 * @bmap: bmap
124 * @key: key
125 * @rec: record
126 *
127 * Description: nilfs_bmap_insert() inserts the new key-record pair specified
128 * by @key and @rec into @bmap.
129 *
130 * Return Value: On success, 0 is returned. On error, one of the following
131 * negative error codes is returned.
132 *
133 * %-EIO - I/O error.
134 *
135 * %-ENOMEM - Insufficient amount of memory available.
136 *
137 * %-EEXIST - A record associated with @key already exist.
138 */
139int nilfs_bmap_insert(struct nilfs_bmap *bmap,
140 unsigned long key,
141 unsigned long rec)
142{
143 int ret;
144
145 down_write(&bmap->b_sem);
146 ret = nilfs_bmap_do_insert(bmap, key, rec);
147 up_write(&bmap->b_sem);
148 return ret;
149}
150
151static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key)
152{
153 __u64 keys[NILFS_BMAP_LARGE_LOW + 1];
154 __u64 ptrs[NILFS_BMAP_LARGE_LOW + 1];
155 int ret, n;
156
157 if (bmap->b_ops->bop_check_delete != NULL) {
Pekka Enberg8acfbf02009-04-06 19:01:49 -0700158 ret = bmap->b_ops->bop_check_delete(bmap, key);
Koji Satobdb265e2009-04-06 19:01:23 -0700159 if (ret > 0) {
Pekka Enberg8acfbf02009-04-06 19:01:49 -0700160 n = bmap->b_ops->bop_gather_data(
Koji Satobdb265e2009-04-06 19:01:23 -0700161 bmap, keys, ptrs, NILFS_BMAP_LARGE_LOW + 1);
162 if (n < 0)
163 return n;
164 ret = nilfs_direct_delete_and_convert(
Ryusuke Konishi30333422009-05-24 00:09:44 +0900165 bmap, key, keys, ptrs, n);
Koji Satobdb265e2009-04-06 19:01:23 -0700166 if (ret == 0)
167 bmap->b_u.u_flags &= ~NILFS_BMAP_LARGE;
168
169 return ret;
170 } else if (ret < 0)
171 return ret;
172 }
173
Pekka Enberg8acfbf02009-04-06 19:01:49 -0700174 return bmap->b_ops->bop_delete(bmap, key);
Koji Satobdb265e2009-04-06 19:01:23 -0700175}
176
177int nilfs_bmap_last_key(struct nilfs_bmap *bmap, unsigned long *key)
178{
179 __u64 lastkey;
180 int ret;
181
182 down_read(&bmap->b_sem);
Pekka Enberg8acfbf02009-04-06 19:01:49 -0700183 ret = bmap->b_ops->bop_last_key(bmap, &lastkey);
Koji Satobdb265e2009-04-06 19:01:23 -0700184 if (!ret)
185 *key = lastkey;
186 up_read(&bmap->b_sem);
187 return ret;
188}
189
190/**
191 * nilfs_bmap_delete - delete a key-record pair from a bmap
192 * @bmap: bmap
193 * @key: key
194 *
195 * Description: nilfs_bmap_delete() deletes the key-record pair specified by
196 * @key from @bmap.
197 *
198 * Return Value: On success, 0 is returned. On error, one of the following
199 * negative error codes is returned.
200 *
201 * %-EIO - I/O error.
202 *
203 * %-ENOMEM - Insufficient amount of memory available.
204 *
205 * %-ENOENT - A record associated with @key does not exist.
206 */
207int nilfs_bmap_delete(struct nilfs_bmap *bmap, unsigned long key)
208{
209 int ret;
210
211 down_write(&bmap->b_sem);
212 ret = nilfs_bmap_do_delete(bmap, key);
213 up_write(&bmap->b_sem);
214 return ret;
215}
216
217static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, unsigned long key)
218{
219 __u64 lastkey;
220 int ret;
221
Pekka Enberg8acfbf02009-04-06 19:01:49 -0700222 ret = bmap->b_ops->bop_last_key(bmap, &lastkey);
Koji Satobdb265e2009-04-06 19:01:23 -0700223 if (ret < 0) {
224 if (ret == -ENOENT)
225 ret = 0;
226 return ret;
227 }
228
229 while (key <= lastkey) {
230 ret = nilfs_bmap_do_delete(bmap, lastkey);
231 if (ret < 0)
232 return ret;
Pekka Enberg8acfbf02009-04-06 19:01:49 -0700233 ret = bmap->b_ops->bop_last_key(bmap, &lastkey);
Koji Satobdb265e2009-04-06 19:01:23 -0700234 if (ret < 0) {
235 if (ret == -ENOENT)
236 ret = 0;
237 return ret;
238 }
239 }
240 return 0;
241}
242
243/**
244 * nilfs_bmap_truncate - truncate a bmap to a specified key
245 * @bmap: bmap
246 * @key: key
247 *
248 * Description: nilfs_bmap_truncate() removes key-record pairs whose keys are
249 * greater than or equal to @key from @bmap.
250 *
251 * Return Value: On success, 0 is returned. On error, one of the following
252 * negative error codes is returned.
253 *
254 * %-EIO - I/O error.
255 *
256 * %-ENOMEM - Insufficient amount of memory available.
257 */
258int nilfs_bmap_truncate(struct nilfs_bmap *bmap, unsigned long key)
259{
260 int ret;
261
262 down_write(&bmap->b_sem);
263 ret = nilfs_bmap_do_truncate(bmap, key);
264 up_write(&bmap->b_sem);
265 return ret;
266}
267
268/**
269 * nilfs_bmap_clear - free resources a bmap holds
270 * @bmap: bmap
271 *
272 * Description: nilfs_bmap_clear() frees resources associated with @bmap.
273 */
274void nilfs_bmap_clear(struct nilfs_bmap *bmap)
275{
276 down_write(&bmap->b_sem);
277 if (bmap->b_ops->bop_clear != NULL)
Pekka Enberg8acfbf02009-04-06 19:01:49 -0700278 bmap->b_ops->bop_clear(bmap);
Koji Satobdb265e2009-04-06 19:01:23 -0700279 up_write(&bmap->b_sem);
280}
281
282/**
283 * nilfs_bmap_propagate - propagate dirty state
284 * @bmap: bmap
285 * @bh: buffer head
286 *
287 * Description: nilfs_bmap_propagate() marks the buffers that directly or
288 * indirectly refer to the block specified by @bh dirty.
289 *
290 * Return Value: On success, 0 is returned. On error, one of the following
291 * negative error codes is returned.
292 *
293 * %-EIO - I/O error.
294 *
295 * %-ENOMEM - Insufficient amount of memory available.
296 */
297int nilfs_bmap_propagate(struct nilfs_bmap *bmap, struct buffer_head *bh)
298{
299 int ret;
300
301 down_write(&bmap->b_sem);
Pekka Enberg8acfbf02009-04-06 19:01:49 -0700302 ret = bmap->b_ops->bop_propagate(bmap, bh);
Koji Satobdb265e2009-04-06 19:01:23 -0700303 up_write(&bmap->b_sem);
304 return ret;
305}
306
307/**
308 * nilfs_bmap_lookup_dirty_buffers -
309 * @bmap: bmap
310 * @listp: pointer to buffer head list
311 */
312void nilfs_bmap_lookup_dirty_buffers(struct nilfs_bmap *bmap,
313 struct list_head *listp)
314{
315 if (bmap->b_ops->bop_lookup_dirty_buffers != NULL)
Pekka Enberg8acfbf02009-04-06 19:01:49 -0700316 bmap->b_ops->bop_lookup_dirty_buffers(bmap, listp);
Koji Satobdb265e2009-04-06 19:01:23 -0700317}
318
319/**
320 * nilfs_bmap_assign - assign a new block number to a block
321 * @bmap: bmap
322 * @bhp: pointer to buffer head
323 * @blocknr: block number
324 * @binfo: block information
325 *
326 * Description: nilfs_bmap_assign() assigns the block number @blocknr to the
327 * buffer specified by @bh.
328 *
329 * Return Value: On success, 0 is returned and the buffer head of a newly
330 * create buffer and the block information associated with the buffer are
331 * stored in the place pointed by @bh and @binfo, respectively. On error, one
332 * of the following negative error codes is returned.
333 *
334 * %-EIO - I/O error.
335 *
336 * %-ENOMEM - Insufficient amount of memory available.
337 */
338int nilfs_bmap_assign(struct nilfs_bmap *bmap,
339 struct buffer_head **bh,
340 unsigned long blocknr,
341 union nilfs_binfo *binfo)
342{
343 int ret;
344
345 down_write(&bmap->b_sem);
Pekka Enberg8acfbf02009-04-06 19:01:49 -0700346 ret = bmap->b_ops->bop_assign(bmap, bh, blocknr, binfo);
Koji Satobdb265e2009-04-06 19:01:23 -0700347 up_write(&bmap->b_sem);
348 return ret;
349}
350
351/**
352 * nilfs_bmap_mark - mark block dirty
353 * @bmap: bmap
354 * @key: key
355 * @level: level
356 *
357 * Description: nilfs_bmap_mark() marks the block specified by @key and @level
358 * as dirty.
359 *
360 * Return Value: On success, 0 is returned. On error, one of the following
361 * negative error codes is returned.
362 *
363 * %-EIO - I/O error.
364 *
365 * %-ENOMEM - Insufficient amount of memory available.
366 */
367int nilfs_bmap_mark(struct nilfs_bmap *bmap, __u64 key, int level)
368{
369 int ret;
370
371 if (bmap->b_ops->bop_mark == NULL)
372 return 0;
373
374 down_write(&bmap->b_sem);
Pekka Enberg8acfbf02009-04-06 19:01:49 -0700375 ret = bmap->b_ops->bop_mark(bmap, key, level);
Koji Satobdb265e2009-04-06 19:01:23 -0700376 up_write(&bmap->b_sem);
377 return ret;
378}
379
380/**
381 * nilfs_bmap_test_and_clear_dirty - test and clear a bmap dirty state
382 * @bmap: bmap
383 *
384 * Description: nilfs_test_and_clear() is the atomic operation to test and
385 * clear the dirty state of @bmap.
386 *
387 * Return Value: 1 is returned if @bmap is dirty, or 0 if clear.
388 */
389int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *bmap)
390{
391 int ret;
392
393 down_write(&bmap->b_sem);
394 ret = nilfs_bmap_dirty(bmap);
395 nilfs_bmap_clear_dirty(bmap);
396 up_write(&bmap->b_sem);
397 return ret;
398}
399
400
401/*
402 * Internal use only
403 */
404
405void nilfs_bmap_add_blocks(const struct nilfs_bmap *bmap, int n)
406{
407 inode_add_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n);
408 if (NILFS_MDT(bmap->b_inode))
409 nilfs_mdt_mark_dirty(bmap->b_inode);
410 else
411 mark_inode_dirty(bmap->b_inode);
412}
413
414void nilfs_bmap_sub_blocks(const struct nilfs_bmap *bmap, int n)
415{
416 inode_sub_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n);
417 if (NILFS_MDT(bmap->b_inode))
418 nilfs_mdt_mark_dirty(bmap->b_inode);
419 else
420 mark_inode_dirty(bmap->b_inode);
421}
422
Koji Satobdb265e2009-04-06 19:01:23 -0700423__u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap,
424 const struct buffer_head *bh)
425{
426 struct buffer_head *pbh;
427 __u64 key;
428
429 key = page_index(bh->b_page) << (PAGE_CACHE_SHIFT -
430 bmap->b_inode->i_blkbits);
431 for (pbh = page_buffers(bh->b_page); pbh != bh;
432 pbh = pbh->b_this_page, key++);
433
434 return key;
435}
436
437__u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *bmap, __u64 key)
438{
439 __s64 diff;
440
441 diff = key - bmap->b_last_allocated_key;
442 if ((nilfs_bmap_keydiff_abs(diff) < NILFS_INODE_BMAP_SIZE) &&
443 (bmap->b_last_allocated_ptr != NILFS_BMAP_INVALID_PTR) &&
444 (bmap->b_last_allocated_ptr + diff > 0))
445 return bmap->b_last_allocated_ptr + diff;
446 else
447 return NILFS_BMAP_INVALID_PTR;
448}
449
Koji Satobdb265e2009-04-06 19:01:23 -0700450#define NILFS_BMAP_GROUP_DIV 8
451__u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *bmap)
452{
453 struct inode *dat = nilfs_bmap_get_dat(bmap);
454 unsigned long entries_per_group = nilfs_palloc_entries_per_group(dat);
455 unsigned long group = bmap->b_inode->i_ino / entries_per_group;
456
457 return group * entries_per_group +
458 (bmap->b_inode->i_ino % NILFS_BMAP_GROUP_DIV) *
459 (entries_per_group / NILFS_BMAP_GROUP_DIV);
460}
461
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900462int nilfs_bmap_prepare_alloc_v(struct nilfs_bmap *bmap,
463 union nilfs_bmap_ptr_req *req)
Koji Satobdb265e2009-04-06 19:01:23 -0700464{
465 return nilfs_dat_prepare_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req);
466}
467
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900468void nilfs_bmap_commit_alloc_v(struct nilfs_bmap *bmap,
469 union nilfs_bmap_ptr_req *req)
Koji Satobdb265e2009-04-06 19:01:23 -0700470{
471 nilfs_dat_commit_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req);
472}
473
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900474void nilfs_bmap_abort_alloc_v(struct nilfs_bmap *bmap,
475 union nilfs_bmap_ptr_req *req)
Koji Satobdb265e2009-04-06 19:01:23 -0700476{
477 nilfs_dat_abort_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req);
478}
479
Ryusuke Konishid97a51a2009-05-03 21:43:01 +0900480int nilfs_bmap_start_v(struct nilfs_bmap *bmap, union nilfs_bmap_ptr_req *req,
481 sector_t blocknr)
Koji Satobdb265e2009-04-06 19:01:23 -0700482{
Ryusuke Konishid97a51a2009-05-03 21:43:01 +0900483 struct inode *dat = nilfs_bmap_get_dat(bmap);
484 int ret;
Koji Satobdb265e2009-04-06 19:01:23 -0700485
Ryusuke Konishid97a51a2009-05-03 21:43:01 +0900486 ret = nilfs_dat_prepare_start(dat, &req->bpr_req);
487 if (likely(!ret))
488 nilfs_dat_commit_start(dat, &req->bpr_req, blocknr);
489 return ret;
Koji Satobdb265e2009-04-06 19:01:23 -0700490}
491
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900492int nilfs_bmap_prepare_end_v(struct nilfs_bmap *bmap,
493 union nilfs_bmap_ptr_req *req)
Koji Satobdb265e2009-04-06 19:01:23 -0700494{
495 return nilfs_dat_prepare_end(nilfs_bmap_get_dat(bmap), &req->bpr_req);
496}
497
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900498void nilfs_bmap_commit_end_v(struct nilfs_bmap *bmap,
499 union nilfs_bmap_ptr_req *req)
Koji Satobdb265e2009-04-06 19:01:23 -0700500{
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900501 nilfs_dat_commit_end(nilfs_bmap_get_dat(bmap), &req->bpr_req,
502 bmap->b_ptr_type == NILFS_BMAP_PTR_VS);
Koji Satobdb265e2009-04-06 19:01:23 -0700503}
504
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900505void nilfs_bmap_abort_end_v(struct nilfs_bmap *bmap,
506 union nilfs_bmap_ptr_req *req)
Koji Satobdb265e2009-04-06 19:01:23 -0700507{
508 nilfs_dat_abort_end(nilfs_bmap_get_dat(bmap), &req->bpr_req);
509}
510
511int nilfs_bmap_move_v(const struct nilfs_bmap *bmap, __u64 vblocknr,
512 sector_t blocknr)
513{
514 return nilfs_dat_move(nilfs_bmap_get_dat(bmap), vblocknr, blocknr);
515}
516
517int nilfs_bmap_mark_dirty(const struct nilfs_bmap *bmap, __u64 vblocknr)
518{
519 return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(bmap), vblocknr);
520}
521
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900522int nilfs_bmap_prepare_update_v(struct nilfs_bmap *bmap,
523 union nilfs_bmap_ptr_req *oldreq,
524 union nilfs_bmap_ptr_req *newreq)
Koji Satobdb265e2009-04-06 19:01:23 -0700525{
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900526 struct inode *dat = nilfs_bmap_get_dat(bmap);
Koji Satobdb265e2009-04-06 19:01:23 -0700527 int ret;
528
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900529 ret = nilfs_dat_prepare_end(dat, &oldreq->bpr_req);
Koji Satobdb265e2009-04-06 19:01:23 -0700530 if (ret < 0)
531 return ret;
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900532 ret = nilfs_dat_prepare_alloc(dat, &newreq->bpr_req);
Koji Satobdb265e2009-04-06 19:01:23 -0700533 if (ret < 0)
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900534 nilfs_dat_abort_end(dat, &oldreq->bpr_req);
Koji Satobdb265e2009-04-06 19:01:23 -0700535
536 return ret;
537}
538
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900539void nilfs_bmap_commit_update_v(struct nilfs_bmap *bmap,
540 union nilfs_bmap_ptr_req *oldreq,
541 union nilfs_bmap_ptr_req *newreq)
Koji Satobdb265e2009-04-06 19:01:23 -0700542{
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900543 struct inode *dat = nilfs_bmap_get_dat(bmap);
544
545 nilfs_dat_commit_end(dat, &oldreq->bpr_req,
546 bmap->b_ptr_type == NILFS_BMAP_PTR_VS);
547 nilfs_dat_commit_alloc(dat, &newreq->bpr_req);
Koji Satobdb265e2009-04-06 19:01:23 -0700548}
549
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900550void nilfs_bmap_abort_update_v(struct nilfs_bmap *bmap,
551 union nilfs_bmap_ptr_req *oldreq,
552 union nilfs_bmap_ptr_req *newreq)
Koji Satobdb265e2009-04-06 19:01:23 -0700553{
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900554 struct inode *dat = nilfs_bmap_get_dat(bmap);
555
556 nilfs_dat_abort_end(dat, &oldreq->bpr_req);
557 nilfs_dat_abort_alloc(dat, &newreq->bpr_req);
Koji Satobdb265e2009-04-06 19:01:23 -0700558}
559
Ryusuke Konishibcb48892009-03-27 02:51:39 +0900560static struct lock_class_key nilfs_bmap_dat_lock_key;
561
Koji Satobdb265e2009-04-06 19:01:23 -0700562/**
563 * nilfs_bmap_read - read a bmap from an inode
564 * @bmap: bmap
565 * @raw_inode: on-disk inode
566 *
567 * Description: nilfs_bmap_read() initializes the bmap @bmap.
568 *
569 * Return Value: On success, 0 is returned. On error, the following negative
570 * error code is returned.
571 *
572 * %-ENOMEM - Insufficient amount of memory available.
573 */
574int nilfs_bmap_read(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode)
575{
576 if (raw_inode == NULL)
577 memset(bmap->b_u.u_data, 0, NILFS_BMAP_SIZE);
578 else
579 memcpy(bmap->b_u.u_data, raw_inode->i_bmap, NILFS_BMAP_SIZE);
580
581 init_rwsem(&bmap->b_sem);
582 bmap->b_state = 0;
583 bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
584 switch (bmap->b_inode->i_ino) {
585 case NILFS_DAT_INO:
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900586 bmap->b_ptr_type = NILFS_BMAP_PTR_P;
587 bmap->b_last_allocated_key = 0;
Koji Satobdb265e2009-04-06 19:01:23 -0700588 bmap->b_last_allocated_ptr = NILFS_BMAP_NEW_PTR_INIT;
Ryusuke Konishibcb48892009-03-27 02:51:39 +0900589 lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key);
Koji Satobdb265e2009-04-06 19:01:23 -0700590 break;
591 case NILFS_CPFILE_INO:
592 case NILFS_SUFILE_INO:
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900593 bmap->b_ptr_type = NILFS_BMAP_PTR_VS;
594 bmap->b_last_allocated_key = 0;
Koji Satobdb265e2009-04-06 19:01:23 -0700595 bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
596 break;
597 default:
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900598 bmap->b_ptr_type = NILFS_BMAP_PTR_VM;
599 bmap->b_last_allocated_key = 0;
Koji Satobdb265e2009-04-06 19:01:23 -0700600 bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
601 break;
602 }
603
604 return (bmap->b_u.u_flags & NILFS_BMAP_LARGE) ?
Ryusuke Konishi30333422009-05-24 00:09:44 +0900605 nilfs_btree_init(bmap) : nilfs_direct_init(bmap);
Koji Satobdb265e2009-04-06 19:01:23 -0700606}
607
608/**
609 * nilfs_bmap_write - write back a bmap to an inode
610 * @bmap: bmap
611 * @raw_inode: on-disk inode
612 *
613 * Description: nilfs_bmap_write() stores @bmap in @raw_inode.
614 */
615void nilfs_bmap_write(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode)
616{
617 down_write(&bmap->b_sem);
618 memcpy(raw_inode->i_bmap, bmap->b_u.u_data,
619 NILFS_INODE_BMAP_SIZE * sizeof(__le64));
620 if (bmap->b_inode->i_ino == NILFS_DAT_INO)
621 bmap->b_last_allocated_ptr = NILFS_BMAP_NEW_PTR_INIT;
622
623 up_write(&bmap->b_sem);
624}
625
626void nilfs_bmap_init_gc(struct nilfs_bmap *bmap)
627{
628 memset(&bmap->b_u, 0, NILFS_BMAP_SIZE);
629 init_rwsem(&bmap->b_sem);
630 bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900631 bmap->b_ptr_type = NILFS_BMAP_PTR_U;
Koji Satobdb265e2009-04-06 19:01:23 -0700632 bmap->b_last_allocated_key = 0;
633 bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
634 bmap->b_state = 0;
635 nilfs_btree_init_gc(bmap);
636}
637
638void nilfs_bmap_init_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap)
639{
640 memcpy(gcbmap, bmap, sizeof(union nilfs_bmap_union));
641 init_rwsem(&gcbmap->b_sem);
Ryusuke Konishibcb48892009-03-27 02:51:39 +0900642 lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key);
Koji Satobdb265e2009-04-06 19:01:23 -0700643 gcbmap->b_inode = &NILFS_BMAP_I(gcbmap)->vfs_inode;
644}
645
646void nilfs_bmap_commit_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap)
647{
648 memcpy(bmap, gcbmap, sizeof(union nilfs_bmap_union));
649 init_rwsem(&bmap->b_sem);
Ryusuke Konishibcb48892009-03-27 02:51:39 +0900650 lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key);
Koji Satobdb265e2009-04-06 19:01:23 -0700651 bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
652}