2 * segbuf.c - NILFS segment buffer
4 * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
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.
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.
16 * Written by Ryusuke Konishi.
20 #include <linux/buffer_head.h>
21 #include <linux/writeback.h>
22 #include <linux/crc32.h>
23 #include <linux/backing-dev.h>
24 #include <linux/slab.h>
29 struct nilfs_write_info
{
30 struct the_nilfs
*nilfs
;
32 int start
, end
; /* The region to be submitted */
39 static int nilfs_segbuf_write(struct nilfs_segment_buffer
*segbuf
,
40 struct the_nilfs
*nilfs
);
41 static int nilfs_segbuf_wait(struct nilfs_segment_buffer
*segbuf
);
43 struct nilfs_segment_buffer
*nilfs_segbuf_new(struct super_block
*sb
)
45 struct nilfs_segment_buffer
*segbuf
;
47 segbuf
= kmem_cache_alloc(nilfs_segbuf_cachep
, GFP_NOFS
);
48 if (unlikely(!segbuf
))
51 segbuf
->sb_super
= sb
;
52 INIT_LIST_HEAD(&segbuf
->sb_list
);
53 INIT_LIST_HEAD(&segbuf
->sb_segsum_buffers
);
54 INIT_LIST_HEAD(&segbuf
->sb_payload_buffers
);
55 segbuf
->sb_super_root
= NULL
;
57 init_completion(&segbuf
->sb_bio_event
);
58 atomic_set(&segbuf
->sb_err
, 0);
64 void nilfs_segbuf_free(struct nilfs_segment_buffer
*segbuf
)
66 kmem_cache_free(nilfs_segbuf_cachep
, segbuf
);
69 void nilfs_segbuf_map(struct nilfs_segment_buffer
*segbuf
, __u64 segnum
,
70 unsigned long offset
, struct the_nilfs
*nilfs
)
72 segbuf
->sb_segnum
= segnum
;
73 nilfs_get_segment_range(nilfs
, segnum
, &segbuf
->sb_fseg_start
,
74 &segbuf
->sb_fseg_end
);
76 segbuf
->sb_pseg_start
= segbuf
->sb_fseg_start
+ offset
;
77 segbuf
->sb_rest_blocks
=
78 segbuf
->sb_fseg_end
- segbuf
->sb_pseg_start
+ 1;
82 * nilfs_segbuf_map_cont - map a new log behind a given log
83 * @segbuf: new segment buffer
84 * @prev: segment buffer containing a log to be continued
86 void nilfs_segbuf_map_cont(struct nilfs_segment_buffer
*segbuf
,
87 struct nilfs_segment_buffer
*prev
)
89 segbuf
->sb_segnum
= prev
->sb_segnum
;
90 segbuf
->sb_fseg_start
= prev
->sb_fseg_start
;
91 segbuf
->sb_fseg_end
= prev
->sb_fseg_end
;
92 segbuf
->sb_pseg_start
= prev
->sb_pseg_start
+ prev
->sb_sum
.nblocks
;
93 segbuf
->sb_rest_blocks
=
94 segbuf
->sb_fseg_end
- segbuf
->sb_pseg_start
+ 1;
97 void nilfs_segbuf_set_next_segnum(struct nilfs_segment_buffer
*segbuf
,
98 __u64 nextnum
, struct the_nilfs
*nilfs
)
100 segbuf
->sb_nextnum
= nextnum
;
101 segbuf
->sb_sum
.next
= nilfs_get_segment_start_blocknr(nilfs
, nextnum
);
104 int nilfs_segbuf_extend_segsum(struct nilfs_segment_buffer
*segbuf
)
106 struct buffer_head
*bh
;
108 bh
= sb_getblk(segbuf
->sb_super
,
109 segbuf
->sb_pseg_start
+ segbuf
->sb_sum
.nsumblk
);
113 nilfs_segbuf_add_segsum_buffer(segbuf
, bh
);
117 int nilfs_segbuf_extend_payload(struct nilfs_segment_buffer
*segbuf
,
118 struct buffer_head
**bhp
)
120 struct buffer_head
*bh
;
122 bh
= sb_getblk(segbuf
->sb_super
,
123 segbuf
->sb_pseg_start
+ segbuf
->sb_sum
.nblocks
);
127 nilfs_segbuf_add_payload_buffer(segbuf
, bh
);
132 int nilfs_segbuf_reset(struct nilfs_segment_buffer
*segbuf
, unsigned int flags
,
133 time_t ctime
, __u64 cno
)
137 segbuf
->sb_sum
.nblocks
= segbuf
->sb_sum
.nsumblk
= 0;
138 err
= nilfs_segbuf_extend_segsum(segbuf
);
142 segbuf
->sb_sum
.flags
= flags
;
143 segbuf
->sb_sum
.sumbytes
= sizeof(struct nilfs_segment_summary
);
144 segbuf
->sb_sum
.nfinfo
= segbuf
->sb_sum
.nfileblk
= 0;
145 segbuf
->sb_sum
.ctime
= ctime
;
146 segbuf
->sb_sum
.cno
= cno
;
151 * Setup segment summary
153 void nilfs_segbuf_fill_in_segsum(struct nilfs_segment_buffer
*segbuf
)
155 struct nilfs_segment_summary
*raw_sum
;
156 struct buffer_head
*bh_sum
;
158 bh_sum
= list_entry(segbuf
->sb_segsum_buffers
.next
,
159 struct buffer_head
, b_assoc_buffers
);
160 raw_sum
= (struct nilfs_segment_summary
*)bh_sum
->b_data
;
162 raw_sum
->ss_magic
= cpu_to_le32(NILFS_SEGSUM_MAGIC
);
163 raw_sum
->ss_bytes
= cpu_to_le16(sizeof(*raw_sum
));
164 raw_sum
->ss_flags
= cpu_to_le16(segbuf
->sb_sum
.flags
);
165 raw_sum
->ss_seq
= cpu_to_le64(segbuf
->sb_sum
.seg_seq
);
166 raw_sum
->ss_create
= cpu_to_le64(segbuf
->sb_sum
.ctime
);
167 raw_sum
->ss_next
= cpu_to_le64(segbuf
->sb_sum
.next
);
168 raw_sum
->ss_nblocks
= cpu_to_le32(segbuf
->sb_sum
.nblocks
);
169 raw_sum
->ss_nfinfo
= cpu_to_le32(segbuf
->sb_sum
.nfinfo
);
170 raw_sum
->ss_sumbytes
= cpu_to_le32(segbuf
->sb_sum
.sumbytes
);
172 raw_sum
->ss_cno
= cpu_to_le64(segbuf
->sb_sum
.cno
);
176 * CRC calculation routines
179 nilfs_segbuf_fill_in_segsum_crc(struct nilfs_segment_buffer
*segbuf
, u32 seed
)
181 struct buffer_head
*bh
;
182 struct nilfs_segment_summary
*raw_sum
;
183 unsigned long size
, bytes
= segbuf
->sb_sum
.sumbytes
;
186 bh
= list_entry(segbuf
->sb_segsum_buffers
.next
, struct buffer_head
,
189 raw_sum
= (struct nilfs_segment_summary
*)bh
->b_data
;
190 size
= min_t(unsigned long, bytes
, bh
->b_size
);
192 (unsigned char *)raw_sum
+
193 sizeof(raw_sum
->ss_datasum
) + sizeof(raw_sum
->ss_sumsum
),
194 size
- (sizeof(raw_sum
->ss_datasum
) +
195 sizeof(raw_sum
->ss_sumsum
)));
197 list_for_each_entry_continue(bh
, &segbuf
->sb_segsum_buffers
,
200 size
= min_t(unsigned long, bytes
, bh
->b_size
);
201 crc
= crc32_le(crc
, bh
->b_data
, size
);
203 raw_sum
->ss_sumsum
= cpu_to_le32(crc
);
206 static void nilfs_segbuf_fill_in_data_crc(struct nilfs_segment_buffer
*segbuf
,
209 struct buffer_head
*bh
;
210 struct nilfs_segment_summary
*raw_sum
;
214 bh
= list_entry(segbuf
->sb_segsum_buffers
.next
, struct buffer_head
,
216 raw_sum
= (struct nilfs_segment_summary
*)bh
->b_data
;
218 (unsigned char *)raw_sum
+ sizeof(raw_sum
->ss_datasum
),
219 bh
->b_size
- sizeof(raw_sum
->ss_datasum
));
221 list_for_each_entry_continue(bh
, &segbuf
->sb_segsum_buffers
,
223 crc
= crc32_le(crc
, bh
->b_data
, bh
->b_size
);
225 list_for_each_entry(bh
, &segbuf
->sb_payload_buffers
, b_assoc_buffers
) {
226 kaddr
= kmap_atomic(bh
->b_page
);
227 crc
= crc32_le(crc
, kaddr
+ bh_offset(bh
), bh
->b_size
);
228 kunmap_atomic(kaddr
);
230 raw_sum
->ss_datasum
= cpu_to_le32(crc
);
234 nilfs_segbuf_fill_in_super_root_crc(struct nilfs_segment_buffer
*segbuf
,
237 struct nilfs_super_root
*raw_sr
;
238 struct the_nilfs
*nilfs
= segbuf
->sb_super
->s_fs_info
;
242 raw_sr
= (struct nilfs_super_root
*)segbuf
->sb_super_root
->b_data
;
243 srsize
= NILFS_SR_BYTES(nilfs
->ns_inode_size
);
245 (unsigned char *)raw_sr
+ sizeof(raw_sr
->sr_sum
),
246 srsize
- sizeof(raw_sr
->sr_sum
));
247 raw_sr
->sr_sum
= cpu_to_le32(crc
);
250 static void nilfs_release_buffers(struct list_head
*list
)
252 struct buffer_head
*bh
, *n
;
254 list_for_each_entry_safe(bh
, n
, list
, b_assoc_buffers
) {
255 list_del_init(&bh
->b_assoc_buffers
);
260 static void nilfs_segbuf_clear(struct nilfs_segment_buffer
*segbuf
)
262 nilfs_release_buffers(&segbuf
->sb_segsum_buffers
);
263 nilfs_release_buffers(&segbuf
->sb_payload_buffers
);
264 segbuf
->sb_super_root
= NULL
;
268 * Iterators for segment buffers
270 void nilfs_clear_logs(struct list_head
*logs
)
272 struct nilfs_segment_buffer
*segbuf
;
274 list_for_each_entry(segbuf
, logs
, sb_list
)
275 nilfs_segbuf_clear(segbuf
);
278 void nilfs_truncate_logs(struct list_head
*logs
,
279 struct nilfs_segment_buffer
*last
)
281 struct nilfs_segment_buffer
*n
, *segbuf
;
283 segbuf
= list_prepare_entry(last
, logs
, sb_list
);
284 list_for_each_entry_safe_continue(segbuf
, n
, logs
, sb_list
) {
285 list_del_init(&segbuf
->sb_list
);
286 nilfs_segbuf_clear(segbuf
);
287 nilfs_segbuf_free(segbuf
);
291 int nilfs_write_logs(struct list_head
*logs
, struct the_nilfs
*nilfs
)
293 struct nilfs_segment_buffer
*segbuf
;
296 list_for_each_entry(segbuf
, logs
, sb_list
) {
297 ret
= nilfs_segbuf_write(segbuf
, nilfs
);
304 int nilfs_wait_on_logs(struct list_head
*logs
)
306 struct nilfs_segment_buffer
*segbuf
;
309 list_for_each_entry(segbuf
, logs
, sb_list
) {
310 err
= nilfs_segbuf_wait(segbuf
);
318 * nilfs_add_checksums_on_logs - add checksums on the logs
319 * @logs: list of segment buffers storing target logs
320 * @seed: checksum seed value
322 void nilfs_add_checksums_on_logs(struct list_head
*logs
, u32 seed
)
324 struct nilfs_segment_buffer
*segbuf
;
326 list_for_each_entry(segbuf
, logs
, sb_list
) {
327 if (segbuf
->sb_super_root
)
328 nilfs_segbuf_fill_in_super_root_crc(segbuf
, seed
);
329 nilfs_segbuf_fill_in_segsum_crc(segbuf
, seed
);
330 nilfs_segbuf_fill_in_data_crc(segbuf
, seed
);
337 static void nilfs_end_bio_write(struct bio
*bio
)
339 struct nilfs_segment_buffer
*segbuf
= bio
->bi_private
;
342 atomic_inc(&segbuf
->sb_err
);
345 complete(&segbuf
->sb_bio_event
);
348 static int nilfs_segbuf_submit_bio(struct nilfs_segment_buffer
*segbuf
,
349 struct nilfs_write_info
*wi
, int mode
)
351 struct bio
*bio
= wi
->bio
;
354 if (segbuf
->sb_nbio
> 0 &&
355 bdi_write_congested(segbuf
->sb_super
->s_bdi
)) {
356 wait_for_completion(&segbuf
->sb_bio_event
);
358 if (unlikely(atomic_read(&segbuf
->sb_err
))) {
365 bio
->bi_end_io
= nilfs_end_bio_write
;
366 bio
->bi_private
= segbuf
;
367 submit_bio(mode
, bio
);
371 wi
->rest_blocks
-= wi
->end
- wi
->start
;
372 wi
->nr_vecs
= min(wi
->max_pages
, wi
->rest_blocks
);
382 * nilfs_alloc_seg_bio - allocate a new bio for writing log
383 * @nilfs: nilfs object
384 * @start: start block number of the bio
385 * @nr_vecs: request size of page vector.
387 * Return Value: On success, pointer to the struct bio is returned.
388 * On error, NULL is returned.
390 static struct bio
*nilfs_alloc_seg_bio(struct the_nilfs
*nilfs
, sector_t start
,
395 bio
= bio_alloc(GFP_NOIO
, nr_vecs
);
397 while (!bio
&& (nr_vecs
>>= 1))
398 bio
= bio_alloc(GFP_NOIO
, nr_vecs
);
401 bio
->bi_bdev
= nilfs
->ns_bdev
;
402 bio
->bi_iter
.bi_sector
=
403 start
<< (nilfs
->ns_blocksize_bits
- 9);
408 static void nilfs_segbuf_prepare_write(struct nilfs_segment_buffer
*segbuf
,
409 struct nilfs_write_info
*wi
)
412 wi
->rest_blocks
= segbuf
->sb_sum
.nblocks
;
413 wi
->max_pages
= BIO_MAX_PAGES
;
414 wi
->nr_vecs
= min(wi
->max_pages
, wi
->rest_blocks
);
415 wi
->start
= wi
->end
= 0;
416 wi
->blocknr
= segbuf
->sb_pseg_start
;
419 static int nilfs_segbuf_submit_bh(struct nilfs_segment_buffer
*segbuf
,
420 struct nilfs_write_info
*wi
,
421 struct buffer_head
*bh
, int mode
)
425 BUG_ON(wi
->nr_vecs
<= 0);
428 wi
->bio
= nilfs_alloc_seg_bio(wi
->nilfs
, wi
->blocknr
+ wi
->end
,
430 if (unlikely(!wi
->bio
))
434 len
= bio_add_page(wi
->bio
, bh
->b_page
, bh
->b_size
, bh_offset(bh
));
435 if (len
== bh
->b_size
) {
440 err
= nilfs_segbuf_submit_bio(segbuf
, wi
, mode
);
441 /* never submit current bh */
448 * nilfs_segbuf_write - submit write requests of a log
449 * @segbuf: buffer storing a log to be written
450 * @nilfs: nilfs object
452 * Return Value: On Success, 0 is returned. On Error, one of the following
453 * negative error code is returned.
457 * %-ENOMEM - Insufficient memory available.
459 static int nilfs_segbuf_write(struct nilfs_segment_buffer
*segbuf
,
460 struct the_nilfs
*nilfs
)
462 struct nilfs_write_info wi
;
463 struct buffer_head
*bh
;
464 int res
= 0, rw
= WRITE
;
467 nilfs_segbuf_prepare_write(segbuf
, &wi
);
469 list_for_each_entry(bh
, &segbuf
->sb_segsum_buffers
, b_assoc_buffers
) {
470 res
= nilfs_segbuf_submit_bh(segbuf
, &wi
, bh
, rw
);
475 list_for_each_entry(bh
, &segbuf
->sb_payload_buffers
, b_assoc_buffers
) {
476 res
= nilfs_segbuf_submit_bh(segbuf
, &wi
, bh
, rw
);
483 * Last BIO is always sent through the following
487 res
= nilfs_segbuf_submit_bio(segbuf
, &wi
, rw
);
495 * nilfs_segbuf_wait - wait for completion of requested BIOs
496 * @segbuf: segment buffer
498 * Return Value: On Success, 0 is returned. On Error, one of the following
499 * negative error code is returned.
503 static int nilfs_segbuf_wait(struct nilfs_segment_buffer
*segbuf
)
507 if (!segbuf
->sb_nbio
)
511 wait_for_completion(&segbuf
->sb_bio_event
);
512 } while (--segbuf
->sb_nbio
> 0);
514 if (unlikely(atomic_read(&segbuf
->sb_err
) > 0)) {
515 printk(KERN_ERR
"NILFS: IO error writing segment\n");
This page took 0.041228 seconds and 5 git commands to generate.