]>
git.ipfire.org Git - people/ms/linux.git/blob - fs/nilfs2/segbuf.c
1 // SPDX-License-Identifier: GPL-2.0+
5 * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
7 * Written by Ryusuke Konishi.
11 #include <linux/buffer_head.h>
12 #include <linux/writeback.h>
13 #include <linux/crc32.h>
14 #include <linux/backing-dev.h>
15 #include <linux/slab.h>
20 struct nilfs_write_info
{
21 struct the_nilfs
*nilfs
;
23 int start
, end
; /* The region to be submitted */
30 static int nilfs_segbuf_write(struct nilfs_segment_buffer
*segbuf
,
31 struct the_nilfs
*nilfs
);
32 static int nilfs_segbuf_wait(struct nilfs_segment_buffer
*segbuf
);
34 struct nilfs_segment_buffer
*nilfs_segbuf_new(struct super_block
*sb
)
36 struct nilfs_segment_buffer
*segbuf
;
38 segbuf
= kmem_cache_alloc(nilfs_segbuf_cachep
, GFP_NOFS
);
39 if (unlikely(!segbuf
))
42 segbuf
->sb_super
= sb
;
43 INIT_LIST_HEAD(&segbuf
->sb_list
);
44 INIT_LIST_HEAD(&segbuf
->sb_segsum_buffers
);
45 INIT_LIST_HEAD(&segbuf
->sb_payload_buffers
);
46 segbuf
->sb_super_root
= NULL
;
48 init_completion(&segbuf
->sb_bio_event
);
49 atomic_set(&segbuf
->sb_err
, 0);
55 void nilfs_segbuf_free(struct nilfs_segment_buffer
*segbuf
)
57 kmem_cache_free(nilfs_segbuf_cachep
, segbuf
);
60 void nilfs_segbuf_map(struct nilfs_segment_buffer
*segbuf
, __u64 segnum
,
61 unsigned long offset
, struct the_nilfs
*nilfs
)
63 segbuf
->sb_segnum
= segnum
;
64 nilfs_get_segment_range(nilfs
, segnum
, &segbuf
->sb_fseg_start
,
65 &segbuf
->sb_fseg_end
);
67 segbuf
->sb_pseg_start
= segbuf
->sb_fseg_start
+ offset
;
68 segbuf
->sb_rest_blocks
=
69 segbuf
->sb_fseg_end
- segbuf
->sb_pseg_start
+ 1;
73 * nilfs_segbuf_map_cont - map a new log behind a given log
74 * @segbuf: new segment buffer
75 * @prev: segment buffer containing a log to be continued
77 void nilfs_segbuf_map_cont(struct nilfs_segment_buffer
*segbuf
,
78 struct nilfs_segment_buffer
*prev
)
80 segbuf
->sb_segnum
= prev
->sb_segnum
;
81 segbuf
->sb_fseg_start
= prev
->sb_fseg_start
;
82 segbuf
->sb_fseg_end
= prev
->sb_fseg_end
;
83 segbuf
->sb_pseg_start
= prev
->sb_pseg_start
+ prev
->sb_sum
.nblocks
;
84 segbuf
->sb_rest_blocks
=
85 segbuf
->sb_fseg_end
- segbuf
->sb_pseg_start
+ 1;
88 void nilfs_segbuf_set_next_segnum(struct nilfs_segment_buffer
*segbuf
,
89 __u64 nextnum
, struct the_nilfs
*nilfs
)
91 segbuf
->sb_nextnum
= nextnum
;
92 segbuf
->sb_sum
.next
= nilfs_get_segment_start_blocknr(nilfs
, nextnum
);
95 int nilfs_segbuf_extend_segsum(struct nilfs_segment_buffer
*segbuf
)
97 struct buffer_head
*bh
;
99 bh
= sb_getblk(segbuf
->sb_super
,
100 segbuf
->sb_pseg_start
+ segbuf
->sb_sum
.nsumblk
);
104 nilfs_segbuf_add_segsum_buffer(segbuf
, bh
);
108 int nilfs_segbuf_extend_payload(struct nilfs_segment_buffer
*segbuf
,
109 struct buffer_head
**bhp
)
111 struct buffer_head
*bh
;
113 bh
= sb_getblk(segbuf
->sb_super
,
114 segbuf
->sb_pseg_start
+ segbuf
->sb_sum
.nblocks
);
118 nilfs_segbuf_add_payload_buffer(segbuf
, bh
);
123 int nilfs_segbuf_reset(struct nilfs_segment_buffer
*segbuf
, unsigned int flags
,
124 time64_t ctime
, __u64 cno
)
128 segbuf
->sb_sum
.nblocks
= segbuf
->sb_sum
.nsumblk
= 0;
129 err
= nilfs_segbuf_extend_segsum(segbuf
);
133 segbuf
->sb_sum
.flags
= flags
;
134 segbuf
->sb_sum
.sumbytes
= sizeof(struct nilfs_segment_summary
);
135 segbuf
->sb_sum
.nfinfo
= segbuf
->sb_sum
.nfileblk
= 0;
136 segbuf
->sb_sum
.ctime
= ctime
;
137 segbuf
->sb_sum
.cno
= cno
;
142 * Setup segment summary
144 void nilfs_segbuf_fill_in_segsum(struct nilfs_segment_buffer
*segbuf
)
146 struct nilfs_segment_summary
*raw_sum
;
147 struct buffer_head
*bh_sum
;
149 bh_sum
= list_entry(segbuf
->sb_segsum_buffers
.next
,
150 struct buffer_head
, b_assoc_buffers
);
151 raw_sum
= (struct nilfs_segment_summary
*)bh_sum
->b_data
;
153 raw_sum
->ss_magic
= cpu_to_le32(NILFS_SEGSUM_MAGIC
);
154 raw_sum
->ss_bytes
= cpu_to_le16(sizeof(*raw_sum
));
155 raw_sum
->ss_flags
= cpu_to_le16(segbuf
->sb_sum
.flags
);
156 raw_sum
->ss_seq
= cpu_to_le64(segbuf
->sb_sum
.seg_seq
);
157 raw_sum
->ss_create
= cpu_to_le64(segbuf
->sb_sum
.ctime
);
158 raw_sum
->ss_next
= cpu_to_le64(segbuf
->sb_sum
.next
);
159 raw_sum
->ss_nblocks
= cpu_to_le32(segbuf
->sb_sum
.nblocks
);
160 raw_sum
->ss_nfinfo
= cpu_to_le32(segbuf
->sb_sum
.nfinfo
);
161 raw_sum
->ss_sumbytes
= cpu_to_le32(segbuf
->sb_sum
.sumbytes
);
163 raw_sum
->ss_cno
= cpu_to_le64(segbuf
->sb_sum
.cno
);
167 * CRC calculation routines
170 nilfs_segbuf_fill_in_segsum_crc(struct nilfs_segment_buffer
*segbuf
, u32 seed
)
172 struct buffer_head
*bh
;
173 struct nilfs_segment_summary
*raw_sum
;
174 unsigned long size
, bytes
= segbuf
->sb_sum
.sumbytes
;
177 bh
= list_entry(segbuf
->sb_segsum_buffers
.next
, struct buffer_head
,
180 raw_sum
= (struct nilfs_segment_summary
*)bh
->b_data
;
181 size
= min_t(unsigned long, bytes
, bh
->b_size
);
183 (unsigned char *)raw_sum
+
184 sizeof(raw_sum
->ss_datasum
) + sizeof(raw_sum
->ss_sumsum
),
185 size
- (sizeof(raw_sum
->ss_datasum
) +
186 sizeof(raw_sum
->ss_sumsum
)));
188 list_for_each_entry_continue(bh
, &segbuf
->sb_segsum_buffers
,
191 size
= min_t(unsigned long, bytes
, bh
->b_size
);
192 crc
= crc32_le(crc
, bh
->b_data
, size
);
194 raw_sum
->ss_sumsum
= cpu_to_le32(crc
);
197 static void nilfs_segbuf_fill_in_data_crc(struct nilfs_segment_buffer
*segbuf
,
200 struct buffer_head
*bh
;
201 struct nilfs_segment_summary
*raw_sum
;
205 bh
= list_entry(segbuf
->sb_segsum_buffers
.next
, struct buffer_head
,
207 raw_sum
= (struct nilfs_segment_summary
*)bh
->b_data
;
209 (unsigned char *)raw_sum
+ sizeof(raw_sum
->ss_datasum
),
210 bh
->b_size
- sizeof(raw_sum
->ss_datasum
));
212 list_for_each_entry_continue(bh
, &segbuf
->sb_segsum_buffers
,
214 crc
= crc32_le(crc
, bh
->b_data
, bh
->b_size
);
216 list_for_each_entry(bh
, &segbuf
->sb_payload_buffers
, b_assoc_buffers
) {
217 kaddr
= kmap_atomic(bh
->b_page
);
218 crc
= crc32_le(crc
, kaddr
+ bh_offset(bh
), bh
->b_size
);
219 kunmap_atomic(kaddr
);
221 raw_sum
->ss_datasum
= cpu_to_le32(crc
);
225 nilfs_segbuf_fill_in_super_root_crc(struct nilfs_segment_buffer
*segbuf
,
228 struct nilfs_super_root
*raw_sr
;
229 struct the_nilfs
*nilfs
= segbuf
->sb_super
->s_fs_info
;
233 raw_sr
= (struct nilfs_super_root
*)segbuf
->sb_super_root
->b_data
;
234 srsize
= NILFS_SR_BYTES(nilfs
->ns_inode_size
);
236 (unsigned char *)raw_sr
+ sizeof(raw_sr
->sr_sum
),
237 srsize
- sizeof(raw_sr
->sr_sum
));
238 raw_sr
->sr_sum
= cpu_to_le32(crc
);
241 static void nilfs_release_buffers(struct list_head
*list
)
243 struct buffer_head
*bh
, *n
;
245 list_for_each_entry_safe(bh
, n
, list
, b_assoc_buffers
) {
246 list_del_init(&bh
->b_assoc_buffers
);
251 static void nilfs_segbuf_clear(struct nilfs_segment_buffer
*segbuf
)
253 nilfs_release_buffers(&segbuf
->sb_segsum_buffers
);
254 nilfs_release_buffers(&segbuf
->sb_payload_buffers
);
255 segbuf
->sb_super_root
= NULL
;
259 * Iterators for segment buffers
261 void nilfs_clear_logs(struct list_head
*logs
)
263 struct nilfs_segment_buffer
*segbuf
;
265 list_for_each_entry(segbuf
, logs
, sb_list
)
266 nilfs_segbuf_clear(segbuf
);
269 void nilfs_truncate_logs(struct list_head
*logs
,
270 struct nilfs_segment_buffer
*last
)
272 struct nilfs_segment_buffer
*n
, *segbuf
;
274 segbuf
= list_prepare_entry(last
, logs
, sb_list
);
275 list_for_each_entry_safe_continue(segbuf
, n
, logs
, sb_list
) {
276 list_del_init(&segbuf
->sb_list
);
277 nilfs_segbuf_clear(segbuf
);
278 nilfs_segbuf_free(segbuf
);
282 int nilfs_write_logs(struct list_head
*logs
, struct the_nilfs
*nilfs
)
284 struct nilfs_segment_buffer
*segbuf
;
287 list_for_each_entry(segbuf
, logs
, sb_list
) {
288 ret
= nilfs_segbuf_write(segbuf
, nilfs
);
295 int nilfs_wait_on_logs(struct list_head
*logs
)
297 struct nilfs_segment_buffer
*segbuf
;
300 list_for_each_entry(segbuf
, logs
, sb_list
) {
301 err
= nilfs_segbuf_wait(segbuf
);
309 * nilfs_add_checksums_on_logs - add checksums on the logs
310 * @logs: list of segment buffers storing target logs
311 * @seed: checksum seed value
313 void nilfs_add_checksums_on_logs(struct list_head
*logs
, u32 seed
)
315 struct nilfs_segment_buffer
*segbuf
;
317 list_for_each_entry(segbuf
, logs
, sb_list
) {
318 if (segbuf
->sb_super_root
)
319 nilfs_segbuf_fill_in_super_root_crc(segbuf
, seed
);
320 nilfs_segbuf_fill_in_segsum_crc(segbuf
, seed
);
321 nilfs_segbuf_fill_in_data_crc(segbuf
, seed
);
328 static void nilfs_end_bio_write(struct bio
*bio
)
330 struct nilfs_segment_buffer
*segbuf
= bio
->bi_private
;
333 atomic_inc(&segbuf
->sb_err
);
336 complete(&segbuf
->sb_bio_event
);
339 static int nilfs_segbuf_submit_bio(struct nilfs_segment_buffer
*segbuf
,
340 struct nilfs_write_info
*wi
)
342 struct bio
*bio
= wi
->bio
;
344 bio
->bi_end_io
= nilfs_end_bio_write
;
345 bio
->bi_private
= segbuf
;
350 wi
->rest_blocks
-= wi
->end
- wi
->start
;
351 wi
->nr_vecs
= min(wi
->max_pages
, wi
->rest_blocks
);
356 static void nilfs_segbuf_prepare_write(struct nilfs_segment_buffer
*segbuf
,
357 struct nilfs_write_info
*wi
)
360 wi
->rest_blocks
= segbuf
->sb_sum
.nblocks
;
361 wi
->max_pages
= BIO_MAX_VECS
;
362 wi
->nr_vecs
= min(wi
->max_pages
, wi
->rest_blocks
);
363 wi
->start
= wi
->end
= 0;
364 wi
->blocknr
= segbuf
->sb_pseg_start
;
367 static int nilfs_segbuf_submit_bh(struct nilfs_segment_buffer
*segbuf
,
368 struct nilfs_write_info
*wi
,
369 struct buffer_head
*bh
)
373 BUG_ON(wi
->nr_vecs
<= 0);
376 wi
->bio
= bio_alloc(wi
->nilfs
->ns_bdev
, wi
->nr_vecs
,
377 REQ_OP_WRITE
, GFP_NOIO
);
378 wi
->bio
->bi_iter
.bi_sector
= (wi
->blocknr
+ wi
->end
) <<
379 (wi
->nilfs
->ns_blocksize_bits
- 9);
382 len
= bio_add_page(wi
->bio
, bh
->b_page
, bh
->b_size
, bh_offset(bh
));
383 if (len
== bh
->b_size
) {
388 err
= nilfs_segbuf_submit_bio(segbuf
, wi
);
389 /* never submit current bh */
396 * nilfs_segbuf_write - submit write requests of a log
397 * @segbuf: buffer storing a log to be written
398 * @nilfs: nilfs object
400 * Return Value: On Success, 0 is returned. On Error, one of the following
401 * negative error code is returned.
405 * %-ENOMEM - Insufficient memory available.
407 static int nilfs_segbuf_write(struct nilfs_segment_buffer
*segbuf
,
408 struct the_nilfs
*nilfs
)
410 struct nilfs_write_info wi
;
411 struct buffer_head
*bh
;
415 nilfs_segbuf_prepare_write(segbuf
, &wi
);
417 list_for_each_entry(bh
, &segbuf
->sb_segsum_buffers
, b_assoc_buffers
) {
418 res
= nilfs_segbuf_submit_bh(segbuf
, &wi
, bh
);
423 list_for_each_entry(bh
, &segbuf
->sb_payload_buffers
, b_assoc_buffers
) {
424 res
= nilfs_segbuf_submit_bh(segbuf
, &wi
, bh
);
431 * Last BIO is always sent through the following
434 wi
.bio
->bi_opf
|= REQ_SYNC
;
435 res
= nilfs_segbuf_submit_bio(segbuf
, &wi
);
443 * nilfs_segbuf_wait - wait for completion of requested BIOs
444 * @segbuf: segment buffer
446 * Return Value: On Success, 0 is returned. On Error, one of the following
447 * negative error code is returned.
451 static int nilfs_segbuf_wait(struct nilfs_segment_buffer
*segbuf
)
455 if (!segbuf
->sb_nbio
)
459 wait_for_completion(&segbuf
->sb_bio_event
);
460 } while (--segbuf
->sb_nbio
> 0);
462 if (unlikely(atomic_read(&segbuf
->sb_err
) > 0)) {
463 nilfs_err(segbuf
->sb_super
,
464 "I/O error writing log (start-blocknr=%llu, block-count=%lu) in segment %llu",
465 (unsigned long long)segbuf
->sb_pseg_start
,
466 segbuf
->sb_sum
.nblocks
,
467 (unsigned long long)segbuf
->sb_segnum
);