Blame view
fs/nilfs2/segbuf.c
13.8 KB
64b5a32e0 nilfs2: segment b... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
/* * segbuf.c - NILFS segment buffer * * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Written by Ryusuke Konishi <ryusuke@osrg.net> * */ #include <linux/buffer_head.h> #include <linux/writeback.h> #include <linux/crc32.h> |
9c965bac1 nilfs2: hide nilf... |
27 |
#include <linux/backing-dev.h> |
5a0e3ad6a include cleanup: ... |
28 |
#include <linux/slab.h> |
64b5a32e0 nilfs2: segment b... |
29 30 |
#include "page.h" #include "segbuf.h" |
64b5a32e0 nilfs2: segment b... |
31 |
|
9c965bac1 nilfs2: hide nilf... |
32 33 34 |
struct nilfs_write_info { struct the_nilfs *nilfs; struct bio *bio; |
55480a06e nilfs2: remove sp... |
35 |
int start, end; /* The region to be submitted */ |
9c965bac1 nilfs2: hide nilf... |
36 37 38 39 40 |
int rest_blocks; int max_pages; int nr_vecs; sector_t blocknr; }; |
d1c6b72a7 nilfs2: move iter... |
41 42 43 |
static int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf, struct the_nilfs *nilfs); static int nilfs_segbuf_wait(struct nilfs_segment_buffer *segbuf); |
64b5a32e0 nilfs2: segment b... |
44 45 46 47 48 49 50 51 52 53 54 55 |
struct nilfs_segment_buffer *nilfs_segbuf_new(struct super_block *sb) { struct nilfs_segment_buffer *segbuf; segbuf = kmem_cache_alloc(nilfs_segbuf_cachep, GFP_NOFS); if (unlikely(!segbuf)) return NULL; segbuf->sb_super = sb; INIT_LIST_HEAD(&segbuf->sb_list); INIT_LIST_HEAD(&segbuf->sb_segsum_buffers); INIT_LIST_HEAD(&segbuf->sb_payload_buffers); |
1e2b68bf2 nilfs2: move poin... |
56 |
segbuf->sb_super_root = NULL; |
9284ad2a9 nilfs2: relocate ... |
57 58 59 60 |
init_completion(&segbuf->sb_bio_event); atomic_set(&segbuf->sb_err, 0); segbuf->sb_nbio = 0; |
64b5a32e0 nilfs2: segment b... |
61 62 63 64 65 |
return segbuf; } void nilfs_segbuf_free(struct nilfs_segment_buffer *segbuf) { |
64b5a32e0 nilfs2: segment b... |
66 67 |
kmem_cache_free(nilfs_segbuf_cachep, segbuf); } |
cece55207 nilfs2: simplify ... |
68 |
void nilfs_segbuf_map(struct nilfs_segment_buffer *segbuf, __u64 segnum, |
64b5a32e0 nilfs2: segment b... |
69 70 |
unsigned long offset, struct the_nilfs *nilfs) { |
64b5a32e0 nilfs2: segment b... |
71 72 73 74 75 76 77 |
segbuf->sb_segnum = segnum; nilfs_get_segment_range(nilfs, segnum, &segbuf->sb_fseg_start, &segbuf->sb_fseg_end); segbuf->sb_pseg_start = segbuf->sb_fseg_start + offset; segbuf->sb_rest_blocks = segbuf->sb_fseg_end - segbuf->sb_pseg_start + 1; |
64b5a32e0 nilfs2: segment b... |
78 |
} |
a694291a6 nilfs2: separate ... |
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
/** * nilfs_segbuf_map_cont - map a new log behind a given log * @segbuf: new segment buffer * @prev: segment buffer containing a log to be continued */ void nilfs_segbuf_map_cont(struct nilfs_segment_buffer *segbuf, struct nilfs_segment_buffer *prev) { segbuf->sb_segnum = prev->sb_segnum; segbuf->sb_fseg_start = prev->sb_fseg_start; segbuf->sb_fseg_end = prev->sb_fseg_end; segbuf->sb_pseg_start = prev->sb_pseg_start + prev->sb_sum.nblocks; segbuf->sb_rest_blocks = segbuf->sb_fseg_end - segbuf->sb_pseg_start + 1; } |
64b5a32e0 nilfs2: segment b... |
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
void nilfs_segbuf_set_next_segnum(struct nilfs_segment_buffer *segbuf, __u64 nextnum, struct the_nilfs *nilfs) { segbuf->sb_nextnum = nextnum; segbuf->sb_sum.next = nilfs_get_segment_start_blocknr(nilfs, nextnum); } int nilfs_segbuf_extend_segsum(struct nilfs_segment_buffer *segbuf) { struct buffer_head *bh; bh = sb_getblk(segbuf->sb_super, segbuf->sb_pseg_start + segbuf->sb_sum.nsumblk); if (unlikely(!bh)) return -ENOMEM; nilfs_segbuf_add_segsum_buffer(segbuf, bh); return 0; } int nilfs_segbuf_extend_payload(struct nilfs_segment_buffer *segbuf, struct buffer_head **bhp) { struct buffer_head *bh; bh = sb_getblk(segbuf->sb_super, segbuf->sb_pseg_start + segbuf->sb_sum.nblocks); if (unlikely(!bh)) return -ENOMEM; nilfs_segbuf_add_payload_buffer(segbuf, bh); *bhp = bh; return 0; } int nilfs_segbuf_reset(struct nilfs_segment_buffer *segbuf, unsigned flags, |
50614bcf2 nilfs2: insert ch... |
130 |
time_t ctime, __u64 cno) |
64b5a32e0 nilfs2: segment b... |
131 132 133 134 135 136 137 138 139 140 141 142 |
{ int err; segbuf->sb_sum.nblocks = segbuf->sb_sum.nsumblk = 0; err = nilfs_segbuf_extend_segsum(segbuf); if (unlikely(err)) return err; segbuf->sb_sum.flags = flags; segbuf->sb_sum.sumbytes = sizeof(struct nilfs_segment_summary); segbuf->sb_sum.nfinfo = segbuf->sb_sum.nfileblk = 0; segbuf->sb_sum.ctime = ctime; |
50614bcf2 nilfs2: insert ch... |
143 |
segbuf->sb_sum.cno = cno; |
64b5a32e0 nilfs2: segment b... |
144 145 146 147 |
return 0; } /* |
7a65004bb nilfs2: fix vario... |
148 |
* Setup segment summary |
64b5a32e0 nilfs2: segment b... |
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
*/ void nilfs_segbuf_fill_in_segsum(struct nilfs_segment_buffer *segbuf) { struct nilfs_segment_summary *raw_sum; struct buffer_head *bh_sum; bh_sum = list_entry(segbuf->sb_segsum_buffers.next, struct buffer_head, b_assoc_buffers); raw_sum = (struct nilfs_segment_summary *)bh_sum->b_data; raw_sum->ss_magic = cpu_to_le32(NILFS_SEGSUM_MAGIC); raw_sum->ss_bytes = cpu_to_le16(sizeof(*raw_sum)); raw_sum->ss_flags = cpu_to_le16(segbuf->sb_sum.flags); raw_sum->ss_seq = cpu_to_le64(segbuf->sb_sum.seg_seq); raw_sum->ss_create = cpu_to_le64(segbuf->sb_sum.ctime); raw_sum->ss_next = cpu_to_le64(segbuf->sb_sum.next); raw_sum->ss_nblocks = cpu_to_le32(segbuf->sb_sum.nblocks); raw_sum->ss_nfinfo = cpu_to_le32(segbuf->sb_sum.nfinfo); raw_sum->ss_sumbytes = cpu_to_le32(segbuf->sb_sum.sumbytes); raw_sum->ss_pad = 0; |
50614bcf2 nilfs2: insert ch... |
169 |
raw_sum->ss_cno = cpu_to_le64(segbuf->sb_sum.cno); |
64b5a32e0 nilfs2: segment b... |
170 171 172 173 174 |
} /* * CRC calculation routines */ |
aaed1d5bf nilfs2: move out ... |
175 176 |
static void nilfs_segbuf_fill_in_segsum_crc(struct nilfs_segment_buffer *segbuf, u32 seed) |
64b5a32e0 nilfs2: segment b... |
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
{ struct buffer_head *bh; struct nilfs_segment_summary *raw_sum; unsigned long size, bytes = segbuf->sb_sum.sumbytes; u32 crc; bh = list_entry(segbuf->sb_segsum_buffers.next, struct buffer_head, b_assoc_buffers); raw_sum = (struct nilfs_segment_summary *)bh->b_data; size = min_t(unsigned long, bytes, bh->b_size); crc = crc32_le(seed, (unsigned char *)raw_sum + sizeof(raw_sum->ss_datasum) + sizeof(raw_sum->ss_sumsum), size - (sizeof(raw_sum->ss_datasum) + sizeof(raw_sum->ss_sumsum))); list_for_each_entry_continue(bh, &segbuf->sb_segsum_buffers, b_assoc_buffers) { bytes -= size; size = min_t(unsigned long, bytes, bh->b_size); crc = crc32_le(crc, bh->b_data, size); } raw_sum->ss_sumsum = cpu_to_le32(crc); } |
aaed1d5bf nilfs2: move out ... |
202 203 |
static void nilfs_segbuf_fill_in_data_crc(struct nilfs_segment_buffer *segbuf, u32 seed) |
64b5a32e0 nilfs2: segment b... |
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
{ struct buffer_head *bh; struct nilfs_segment_summary *raw_sum; void *kaddr; u32 crc; bh = list_entry(segbuf->sb_segsum_buffers.next, struct buffer_head, b_assoc_buffers); raw_sum = (struct nilfs_segment_summary *)bh->b_data; crc = crc32_le(seed, (unsigned char *)raw_sum + sizeof(raw_sum->ss_datasum), bh->b_size - sizeof(raw_sum->ss_datasum)); list_for_each_entry_continue(bh, &segbuf->sb_segsum_buffers, b_assoc_buffers) { crc = crc32_le(crc, bh->b_data, bh->b_size); } list_for_each_entry(bh, &segbuf->sb_payload_buffers, b_assoc_buffers) { kaddr = kmap_atomic(bh->b_page, KM_USER0); crc = crc32_le(crc, kaddr + bh_offset(bh), bh->b_size); kunmap_atomic(kaddr, KM_USER0); } raw_sum->ss_datasum = cpu_to_le32(crc); } |
aaed1d5bf nilfs2: move out ... |
228 229 230 231 232 |
static void nilfs_segbuf_fill_in_super_root_crc(struct nilfs_segment_buffer *segbuf, u32 seed) { struct nilfs_super_root *raw_sr; |
6c6de1aa6 nilfs2: super roo... |
233 234 |
struct the_nilfs *nilfs = segbuf->sb_super->s_fs_info; unsigned srsize; |
aaed1d5bf nilfs2: move out ... |
235 236 237 |
u32 crc; raw_sr = (struct nilfs_super_root *)segbuf->sb_super_root->b_data; |
6c6de1aa6 nilfs2: super roo... |
238 |
srsize = NILFS_SR_BYTES(nilfs->ns_inode_size); |
aaed1d5bf nilfs2: move out ... |
239 240 |
crc = crc32_le(seed, (unsigned char *)raw_sr + sizeof(raw_sr->sr_sum), |
6c6de1aa6 nilfs2: super roo... |
241 |
srsize - sizeof(raw_sr->sr_sum)); |
aaed1d5bf nilfs2: move out ... |
242 243 |
raw_sr->sr_sum = cpu_to_le32(crc); } |
e29df395b nilfs2: add itera... |
244 |
static void nilfs_release_buffers(struct list_head *list) |
64b5a32e0 nilfs2: segment b... |
245 246 247 248 249 |
{ struct buffer_head *bh, *n; list_for_each_entry_safe(bh, n, list, b_assoc_buffers) { list_del_init(&bh->b_assoc_buffers); |
64b5a32e0 nilfs2: segment b... |
250 251 252 |
brelse(bh); } } |
e29df395b nilfs2: add itera... |
253 254 255 256 |
static void nilfs_segbuf_clear(struct nilfs_segment_buffer *segbuf) { nilfs_release_buffers(&segbuf->sb_segsum_buffers); nilfs_release_buffers(&segbuf->sb_payload_buffers); |
1e2b68bf2 nilfs2: move poin... |
257 |
segbuf->sb_super_root = NULL; |
e29df395b nilfs2: add itera... |
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
} /* * Iterators for segment buffers */ void nilfs_clear_logs(struct list_head *logs) { struct nilfs_segment_buffer *segbuf; list_for_each_entry(segbuf, logs, sb_list) nilfs_segbuf_clear(segbuf); } void nilfs_truncate_logs(struct list_head *logs, struct nilfs_segment_buffer *last) { struct nilfs_segment_buffer *n, *segbuf; segbuf = list_prepare_entry(last, logs, sb_list); list_for_each_entry_safe_continue(segbuf, n, logs, sb_list) { list_del_init(&segbuf->sb_list); nilfs_segbuf_clear(segbuf); nilfs_segbuf_free(segbuf); } } |
d1c6b72a7 nilfs2: move iter... |
283 284 285 286 287 288 289 290 291 292 293 294 |
int nilfs_write_logs(struct list_head *logs, struct the_nilfs *nilfs) { struct nilfs_segment_buffer *segbuf; int ret = 0; list_for_each_entry(segbuf, logs, sb_list) { ret = nilfs_segbuf_write(segbuf, nilfs); if (ret) break; } return ret; } |
e29df395b nilfs2: add itera... |
295 296 297 |
int nilfs_wait_on_logs(struct list_head *logs) { struct nilfs_segment_buffer *segbuf; |
d067633b4 nilfs2: fix imper... |
298 |
int err, ret = 0; |
e29df395b nilfs2: add itera... |
299 300 301 |
list_for_each_entry(segbuf, logs, sb_list) { err = nilfs_segbuf_wait(segbuf); |
d067633b4 nilfs2: fix imper... |
302 303 |
if (err && !ret) ret = err; |
e29df395b nilfs2: add itera... |
304 |
} |
d067633b4 nilfs2: fix imper... |
305 |
return ret; |
e29df395b nilfs2: add itera... |
306 |
} |
aaed1d5bf nilfs2: move out ... |
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 |
/** * nilfs_add_checksums_on_logs - add checksums on the logs * @logs: list of segment buffers storing target logs * @seed: checksum seed value */ void nilfs_add_checksums_on_logs(struct list_head *logs, u32 seed) { struct nilfs_segment_buffer *segbuf; list_for_each_entry(segbuf, logs, sb_list) { if (segbuf->sb_super_root) nilfs_segbuf_fill_in_super_root_crc(segbuf, seed); nilfs_segbuf_fill_in_segsum_crc(segbuf, seed); nilfs_segbuf_fill_in_data_crc(segbuf, seed); } } |
64b5a32e0 nilfs2: segment b... |
323 324 325 326 327 328 |
/* * BIO operations */ static void nilfs_end_bio_write(struct bio *bio, int err) { const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); |
9284ad2a9 nilfs2: relocate ... |
329 |
struct nilfs_segment_buffer *segbuf = bio->bi_private; |
64b5a32e0 nilfs2: segment b... |
330 331 332 333 334 335 336 337 |
if (err == -EOPNOTSUPP) { set_bit(BIO_EOPNOTSUPP, &bio->bi_flags); bio_put(bio); /* to be detected by submit_seg_bio() */ } if (!uptodate) |
9284ad2a9 nilfs2: relocate ... |
338 |
atomic_inc(&segbuf->sb_err); |
64b5a32e0 nilfs2: segment b... |
339 340 |
bio_put(bio); |
9284ad2a9 nilfs2: relocate ... |
341 |
complete(&segbuf->sb_bio_event); |
64b5a32e0 nilfs2: segment b... |
342 |
} |
9284ad2a9 nilfs2: relocate ... |
343 344 |
static int nilfs_segbuf_submit_bio(struct nilfs_segment_buffer *segbuf, struct nilfs_write_info *wi, int mode) |
64b5a32e0 nilfs2: segment b... |
345 346 347 |
{ struct bio *bio = wi->bio; int err; |
026a7d63d nilfs2: get rid o... |
348 349 |
if (segbuf->sb_nbio > 0 && bdi_write_congested(segbuf->sb_super->s_bdi)) { |
9284ad2a9 nilfs2: relocate ... |
350 351 352 |
wait_for_completion(&segbuf->sb_bio_event); segbuf->sb_nbio--; if (unlikely(atomic_read(&segbuf->sb_err))) { |
64b5a32e0 nilfs2: segment b... |
353 354 355 356 357 358 359 |
bio_put(bio); err = -EIO; goto failed; } } bio->bi_end_io = nilfs_end_bio_write; |
9284ad2a9 nilfs2: relocate ... |
360 |
bio->bi_private = segbuf; |
64b5a32e0 nilfs2: segment b... |
361 362 363 364 365 366 367 |
bio_get(bio); submit_bio(mode, bio); if (bio_flagged(bio, BIO_EOPNOTSUPP)) { bio_put(bio); err = -EOPNOTSUPP; goto failed; } |
9284ad2a9 nilfs2: relocate ... |
368 |
segbuf->sb_nbio++; |
64b5a32e0 nilfs2: segment b... |
369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
bio_put(bio); wi->bio = NULL; wi->rest_blocks -= wi->end - wi->start; wi->nr_vecs = min(wi->max_pages, wi->rest_blocks); wi->start = wi->end; return 0; failed: wi->bio = NULL; return err; } /** |
9c965bac1 nilfs2: hide nilf... |
383 384 385 |
* nilfs_alloc_seg_bio - allocate a new bio for writing log * @nilfs: nilfs object * @start: start block number of the bio |
64b5a32e0 nilfs2: segment b... |
386 387 |
* @nr_vecs: request size of page vector. * |
64b5a32e0 nilfs2: segment b... |
388 389 390 |
* Return Value: On success, pointer to the struct bio is returned. * On error, NULL is returned. */ |
9c965bac1 nilfs2: hide nilf... |
391 |
static struct bio *nilfs_alloc_seg_bio(struct the_nilfs *nilfs, sector_t start, |
64b5a32e0 nilfs2: segment b... |
392 393 394 |
int nr_vecs) { struct bio *bio; |
c1b353f04 nilfs2: use GFP_N... |
395 |
bio = bio_alloc(GFP_NOIO, nr_vecs); |
64b5a32e0 nilfs2: segment b... |
396 397 |
if (bio == NULL) { while (!bio && (nr_vecs >>= 1)) |
c1b353f04 nilfs2: use GFP_N... |
398 |
bio = bio_alloc(GFP_NOIO, nr_vecs); |
64b5a32e0 nilfs2: segment b... |
399 400 |
} if (likely(bio)) { |
9c965bac1 nilfs2: hide nilf... |
401 402 |
bio->bi_bdev = nilfs->ns_bdev; bio->bi_sector = start << (nilfs->ns_blocksize_bits - 9); |
64b5a32e0 nilfs2: segment b... |
403 404 405 |
} return bio; } |
9c965bac1 nilfs2: hide nilf... |
406 407 |
static void nilfs_segbuf_prepare_write(struct nilfs_segment_buffer *segbuf, struct nilfs_write_info *wi) |
64b5a32e0 nilfs2: segment b... |
408 409 410 |
{ wi->bio = NULL; wi->rest_blocks = segbuf->sb_sum.nblocks; |
9c965bac1 nilfs2: hide nilf... |
411 |
wi->max_pages = bio_get_nr_vecs(wi->nilfs->ns_bdev); |
64b5a32e0 nilfs2: segment b... |
412 413 |
wi->nr_vecs = min(wi->max_pages, wi->rest_blocks); wi->start = wi->end = 0; |
64b5a32e0 nilfs2: segment b... |
414 |
wi->blocknr = segbuf->sb_pseg_start; |
64b5a32e0 nilfs2: segment b... |
415 |
} |
9284ad2a9 nilfs2: relocate ... |
416 417 418 |
static int nilfs_segbuf_submit_bh(struct nilfs_segment_buffer *segbuf, struct nilfs_write_info *wi, struct buffer_head *bh, int mode) |
64b5a32e0 nilfs2: segment b... |
419 420 421 422 423 424 |
{ int len, err; BUG_ON(wi->nr_vecs <= 0); repeat: if (!wi->bio) { |
9c965bac1 nilfs2: hide nilf... |
425 |
wi->bio = nilfs_alloc_seg_bio(wi->nilfs, wi->blocknr + wi->end, |
64b5a32e0 nilfs2: segment b... |
426 427 428 429 430 431 432 433 434 435 436 |
wi->nr_vecs); if (unlikely(!wi->bio)) return -ENOMEM; } len = bio_add_page(wi->bio, bh->b_page, bh->b_size, bh_offset(bh)); if (len == bh->b_size) { wi->end++; return 0; } /* bio is FULL */ |
9284ad2a9 nilfs2: relocate ... |
437 |
err = nilfs_segbuf_submit_bio(segbuf, wi, mode); |
64b5a32e0 nilfs2: segment b... |
438 439 440 441 442 |
/* never submit current bh */ if (likely(!err)) goto repeat; return err; } |
9c965bac1 nilfs2: hide nilf... |
443 444 445 446 447 448 449 450 451 452 453 454 |
/** * nilfs_segbuf_write - submit write requests of a log * @segbuf: buffer storing a log to be written * @nilfs: nilfs object * * Return Value: On Success, 0 is returned. On Error, one of the following * negative error code is returned. * * %-EIO - I/O error * * %-ENOMEM - Insufficient memory available. */ |
6c477d44a nilfs2: fix discr... |
455 456 |
static int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf, struct the_nilfs *nilfs) |
64b5a32e0 nilfs2: segment b... |
457 |
{ |
9c965bac1 nilfs2: hide nilf... |
458 |
struct nilfs_write_info wi; |
64b5a32e0 nilfs2: segment b... |
459 |
struct buffer_head *bh; |
5f1586d0d nilfs2: do not re... |
460 |
int res = 0, rw = WRITE; |
64b5a32e0 nilfs2: segment b... |
461 |
|
9c965bac1 nilfs2: hide nilf... |
462 463 |
wi.nilfs = nilfs; nilfs_segbuf_prepare_write(segbuf, &wi); |
64b5a32e0 nilfs2: segment b... |
464 |
list_for_each_entry(bh, &segbuf->sb_segsum_buffers, b_assoc_buffers) { |
9c965bac1 nilfs2: hide nilf... |
465 |
res = nilfs_segbuf_submit_bh(segbuf, &wi, bh, rw); |
64b5a32e0 nilfs2: segment b... |
466 467 468 469 470 |
if (unlikely(res)) goto failed_bio; } list_for_each_entry(bh, &segbuf->sb_payload_buffers, b_assoc_buffers) { |
9c965bac1 nilfs2: hide nilf... |
471 |
res = nilfs_segbuf_submit_bh(segbuf, &wi, bh, rw); |
64b5a32e0 nilfs2: segment b... |
472 473 474 |
if (unlikely(res)) goto failed_bio; } |
9c965bac1 nilfs2: hide nilf... |
475 |
if (wi.bio) { |
64b5a32e0 nilfs2: segment b... |
476 477 478 479 |
/* * Last BIO is always sent through the following * submission. */ |
721a9602e block: kill off R... |
480 |
rw |= REQ_SYNC; |
9c965bac1 nilfs2: hide nilf... |
481 |
res = nilfs_segbuf_submit_bio(segbuf, &wi, rw); |
64b5a32e0 nilfs2: segment b... |
482 |
} |
64b5a32e0 nilfs2: segment b... |
483 |
failed_bio: |
5f1586d0d nilfs2: do not re... |
484 |
return res; |
64b5a32e0 nilfs2: segment b... |
485 486 487 488 |
} /** * nilfs_segbuf_wait - wait for completion of requested BIOs |
9284ad2a9 nilfs2: relocate ... |
489 |
* @segbuf: segment buffer |
64b5a32e0 nilfs2: segment b... |
490 491 492 493 494 495 |
* * Return Value: On Success, 0 is returned. On Error, one of the following * negative error code is returned. * * %-EIO - I/O error */ |
6c477d44a nilfs2: fix discr... |
496 |
static int nilfs_segbuf_wait(struct nilfs_segment_buffer *segbuf) |
64b5a32e0 nilfs2: segment b... |
497 498 |
{ int err = 0; |
9284ad2a9 nilfs2: relocate ... |
499 |
if (!segbuf->sb_nbio) |
64b5a32e0 nilfs2: segment b... |
500 501 502 |
return 0; do { |
9284ad2a9 nilfs2: relocate ... |
503 504 |
wait_for_completion(&segbuf->sb_bio_event); } while (--segbuf->sb_nbio > 0); |
64b5a32e0 nilfs2: segment b... |
505 |
|
9284ad2a9 nilfs2: relocate ... |
506 |
if (unlikely(atomic_read(&segbuf->sb_err) > 0)) { |
64b5a32e0 nilfs2: segment b... |
507 508 509 |
printk(KERN_ERR "NILFS: IO error writing segment "); err = -EIO; |
64b5a32e0 nilfs2: segment b... |
510 511 512 |
} return err; } |