1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 "btree.h"
29#include "direct.h"
30#include "btnode.h"
31#include "mdt.h"
32#include "dat.h"
33#include "alloc.h"
34
35struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap)
36{
37 struct the_nilfs *nilfs = bmap->b_inode->i_sb->s_fs_info;
38
39 return nilfs->ns_dat;
40}
41
42static int nilfs_bmap_convert_error(struct nilfs_bmap *bmap,
43 const char *fname, int err)
44{
45 struct inode *inode = bmap->b_inode;
46
47 if (err == -EINVAL) {
48 nilfs_error(inode->i_sb, fname,
49 "broken bmap (inode number=%lu)\n", inode->i_ino);
50 err = -EIO;
51 }
52 return err;
53}
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level,
76 __u64 *ptrp)
77{
78 sector_t blocknr;
79 int ret;
80
81 down_read(&bmap->b_sem);
82 ret = bmap->b_ops->bop_lookup(bmap, key, level, ptrp);
83 if (ret < 0) {
84 ret = nilfs_bmap_convert_error(bmap, __func__, ret);
85 goto out;
86 }
87 if (NILFS_BMAP_USE_VBN(bmap)) {
88 ret = nilfs_dat_translate(nilfs_bmap_get_dat(bmap), *ptrp,
89 &blocknr);
90 if (!ret)
91 *ptrp = blocknr;
92 }
93
94 out:
95 up_read(&bmap->b_sem);
96 return ret;
97}
98
99int nilfs_bmap_lookup_contig(struct nilfs_bmap *bmap, __u64 key, __u64 *ptrp,
100 unsigned maxblocks)
101{
102 int ret;
103
104 down_read(&bmap->b_sem);
105 ret = bmap->b_ops->bop_lookup_contig(bmap, key, ptrp, maxblocks);
106 up_read(&bmap->b_sem);
107
108 return nilfs_bmap_convert_error(bmap, __func__, ret);
109}
110
111static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
112{
113 __u64 keys[NILFS_BMAP_SMALL_HIGH + 1];
114 __u64 ptrs[NILFS_BMAP_SMALL_HIGH + 1];
115 int ret, n;
116
117 if (bmap->b_ops->bop_check_insert != NULL) {
118 ret = bmap->b_ops->bop_check_insert(bmap, key);
119 if (ret > 0) {
120 n = bmap->b_ops->bop_gather_data(
121 bmap, keys, ptrs, NILFS_BMAP_SMALL_HIGH + 1);
122 if (n < 0)
123 return n;
124 ret = nilfs_btree_convert_and_insert(
125 bmap, key, ptr, keys, ptrs, n);
126 if (ret == 0)
127 bmap->b_u.u_flags |= NILFS_BMAP_LARGE;
128
129 return ret;
130 } else if (ret < 0)
131 return ret;
132 }
133
134 return bmap->b_ops->bop_insert(bmap, key, ptr);
135}
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155int nilfs_bmap_insert(struct nilfs_bmap *bmap,
156 unsigned long key,
157 unsigned long rec)
158{
159 int ret;
160
161 down_write(&bmap->b_sem);
162 ret = nilfs_bmap_do_insert(bmap, key, rec);
163 up_write(&bmap->b_sem);
164
165 return nilfs_bmap_convert_error(bmap, __func__, ret);
166}
167
168static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key)
169{
170 __u64 keys[NILFS_BMAP_LARGE_LOW + 1];
171 __u64 ptrs[NILFS_BMAP_LARGE_LOW + 1];
172 int ret, n;
173
174 if (bmap->b_ops->bop_check_delete != NULL) {
175 ret = bmap->b_ops->bop_check_delete(bmap, key);
176 if (ret > 0) {
177 n = bmap->b_ops->bop_gather_data(
178 bmap, keys, ptrs, NILFS_BMAP_LARGE_LOW + 1);
179 if (n < 0)
180 return n;
181 ret = nilfs_direct_delete_and_convert(
182 bmap, key, keys, ptrs, n);
183 if (ret == 0)
184 bmap->b_u.u_flags &= ~NILFS_BMAP_LARGE;
185
186 return ret;
187 } else if (ret < 0)
188 return ret;
189 }
190
191 return bmap->b_ops->bop_delete(bmap, key);
192}
193
194int nilfs_bmap_last_key(struct nilfs_bmap *bmap, unsigned long *key)
195{
196 __u64 lastkey;
197 int ret;
198
199 down_read(&bmap->b_sem);
200 ret = bmap->b_ops->bop_last_key(bmap, &lastkey);
201 up_read(&bmap->b_sem);
202
203 if (ret < 0)
204 ret = nilfs_bmap_convert_error(bmap, __func__, ret);
205 else
206 *key = lastkey;
207 return ret;
208}
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227int nilfs_bmap_delete(struct nilfs_bmap *bmap, unsigned long key)
228{
229 int ret;
230
231 down_write(&bmap->b_sem);
232 ret = nilfs_bmap_do_delete(bmap, key);
233 up_write(&bmap->b_sem);
234
235 return nilfs_bmap_convert_error(bmap, __func__, ret);
236}
237
238static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, unsigned long key)
239{
240 __u64 lastkey;
241 int ret;
242
243 ret = bmap->b_ops->bop_last_key(bmap, &lastkey);
244 if (ret < 0) {
245 if (ret == -ENOENT)
246 ret = 0;
247 return ret;
248 }
249
250 while (key <= lastkey) {
251 ret = nilfs_bmap_do_delete(bmap, lastkey);
252 if (ret < 0)
253 return ret;
254 ret = bmap->b_ops->bop_last_key(bmap, &lastkey);
255 if (ret < 0) {
256 if (ret == -ENOENT)
257 ret = 0;
258 return ret;
259 }
260 }
261 return 0;
262}
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279int nilfs_bmap_truncate(struct nilfs_bmap *bmap, unsigned long key)
280{
281 int ret;
282
283 down_write(&bmap->b_sem);
284 ret = nilfs_bmap_do_truncate(bmap, key);
285 up_write(&bmap->b_sem);
286
287 return nilfs_bmap_convert_error(bmap, __func__, ret);
288}
289
290
291
292
293
294
295
296void nilfs_bmap_clear(struct nilfs_bmap *bmap)
297{
298 down_write(&bmap->b_sem);
299 if (bmap->b_ops->bop_clear != NULL)
300 bmap->b_ops->bop_clear(bmap);
301 up_write(&bmap->b_sem);
302}
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319int nilfs_bmap_propagate(struct nilfs_bmap *bmap, struct buffer_head *bh)
320{
321 int ret;
322
323 down_write(&bmap->b_sem);
324 ret = bmap->b_ops->bop_propagate(bmap, bh);
325 up_write(&bmap->b_sem);
326
327 return nilfs_bmap_convert_error(bmap, __func__, ret);
328}
329
330
331
332
333
334
335void nilfs_bmap_lookup_dirty_buffers(struct nilfs_bmap *bmap,
336 struct list_head *listp)
337{
338 if (bmap->b_ops->bop_lookup_dirty_buffers != NULL)
339 bmap->b_ops->bop_lookup_dirty_buffers(bmap, listp);
340}
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361int nilfs_bmap_assign(struct nilfs_bmap *bmap,
362 struct buffer_head **bh,
363 unsigned long blocknr,
364 union nilfs_binfo *binfo)
365{
366 int ret;
367
368 down_write(&bmap->b_sem);
369 ret = bmap->b_ops->bop_assign(bmap, bh, blocknr, binfo);
370 up_write(&bmap->b_sem);
371
372 return nilfs_bmap_convert_error(bmap, __func__, ret);
373}
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391int nilfs_bmap_mark(struct nilfs_bmap *bmap, __u64 key, int level)
392{
393 int ret;
394
395 if (bmap->b_ops->bop_mark == NULL)
396 return 0;
397
398 down_write(&bmap->b_sem);
399 ret = bmap->b_ops->bop_mark(bmap, key, level);
400 up_write(&bmap->b_sem);
401
402 return nilfs_bmap_convert_error(bmap, __func__, ret);
403}
404
405
406
407
408
409
410
411
412
413
414int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *bmap)
415{
416 int ret;
417
418 down_write(&bmap->b_sem);
419 ret = nilfs_bmap_dirty(bmap);
420 nilfs_bmap_clear_dirty(bmap);
421 up_write(&bmap->b_sem);
422 return ret;
423}
424
425
426
427
428
429__u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap,
430 const struct buffer_head *bh)
431{
432 struct buffer_head *pbh;
433 __u64 key;
434
435 key = page_index(bh->b_page) << (PAGE_CACHE_SHIFT -
436 bmap->b_inode->i_blkbits);
437 for (pbh = page_buffers(bh->b_page); pbh != bh; pbh = pbh->b_this_page)
438 key++;
439
440 return key;
441}
442
443__u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *bmap, __u64 key)
444{
445 __s64 diff;
446
447 diff = key - bmap->b_last_allocated_key;
448 if ((nilfs_bmap_keydiff_abs(diff) < NILFS_INODE_BMAP_SIZE) &&
449 (bmap->b_last_allocated_ptr != NILFS_BMAP_INVALID_PTR) &&
450 (bmap->b_last_allocated_ptr + diff > 0))
451 return bmap->b_last_allocated_ptr + diff;
452 else
453 return NILFS_BMAP_INVALID_PTR;
454}
455
456#define NILFS_BMAP_GROUP_DIV 8
457__u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *bmap)
458{
459 struct inode *dat = nilfs_bmap_get_dat(bmap);
460 unsigned long entries_per_group = nilfs_palloc_entries_per_group(dat);
461 unsigned long group = bmap->b_inode->i_ino / entries_per_group;
462
463 return group * entries_per_group +
464 (bmap->b_inode->i_ino % NILFS_BMAP_GROUP_DIV) *
465 (entries_per_group / NILFS_BMAP_GROUP_DIV);
466}
467
468static struct lock_class_key nilfs_bmap_dat_lock_key;
469static struct lock_class_key nilfs_bmap_mdt_lock_key;
470
471
472
473
474
475
476
477
478
479
480
481
482
483int nilfs_bmap_read(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode)
484{
485 if (raw_inode == NULL)
486 memset(bmap->b_u.u_data, 0, NILFS_BMAP_SIZE);
487 else
488 memcpy(bmap->b_u.u_data, raw_inode->i_bmap, NILFS_BMAP_SIZE);
489
490 init_rwsem(&bmap->b_sem);
491 bmap->b_state = 0;
492 bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
493 switch (bmap->b_inode->i_ino) {
494 case NILFS_DAT_INO:
495 bmap->b_ptr_type = NILFS_BMAP_PTR_P;
496 bmap->b_last_allocated_key = 0;
497 bmap->b_last_allocated_ptr = NILFS_BMAP_NEW_PTR_INIT;
498 lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key);
499 break;
500 case NILFS_CPFILE_INO:
501 case NILFS_SUFILE_INO:
502 bmap->b_ptr_type = NILFS_BMAP_PTR_VS;
503 bmap->b_last_allocated_key = 0;
504 bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
505 lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key);
506 break;
507 case NILFS_IFILE_INO:
508 lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key);
509
510 default:
511 bmap->b_ptr_type = NILFS_BMAP_PTR_VM;
512 bmap->b_last_allocated_key = 0;
513 bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
514 break;
515 }
516
517 return (bmap->b_u.u_flags & NILFS_BMAP_LARGE) ?
518 nilfs_btree_init(bmap) : nilfs_direct_init(bmap);
519}
520
521
522
523
524
525
526
527
528void nilfs_bmap_write(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode)
529{
530 down_write(&bmap->b_sem);
531 memcpy(raw_inode->i_bmap, bmap->b_u.u_data,
532 NILFS_INODE_BMAP_SIZE * sizeof(__le64));
533 if (bmap->b_inode->i_ino == NILFS_DAT_INO)
534 bmap->b_last_allocated_ptr = NILFS_BMAP_NEW_PTR_INIT;
535
536 up_write(&bmap->b_sem);
537}
538
539void nilfs_bmap_init_gc(struct nilfs_bmap *bmap)
540{
541 memset(&bmap->b_u, 0, NILFS_BMAP_SIZE);
542 init_rwsem(&bmap->b_sem);
543 bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
544 bmap->b_ptr_type = NILFS_BMAP_PTR_U;
545 bmap->b_last_allocated_key = 0;
546 bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
547 bmap->b_state = 0;
548 nilfs_btree_init_gc(bmap);
549}
550
551void nilfs_bmap_save(const struct nilfs_bmap *bmap,
552 struct nilfs_bmap_store *store)
553{
554 memcpy(store->data, bmap->b_u.u_data, sizeof(store->data));
555 store->last_allocated_key = bmap->b_last_allocated_key;
556 store->last_allocated_ptr = bmap->b_last_allocated_ptr;
557 store->state = bmap->b_state;
558}
559
560void nilfs_bmap_restore(struct nilfs_bmap *bmap,
561 const struct nilfs_bmap_store *store)
562{
563 memcpy(bmap->b_u.u_data, store->data, sizeof(store->data));
564 bmap->b_last_allocated_key = store->last_allocated_key;
565 bmap->b_last_allocated_ptr = store->last_allocated_ptr;
566 bmap->b_state = store->state;
567}
568