diff options
Diffstat (limited to 'fs/nilfs2')
-rw-r--r-- | fs/nilfs2/segbuf.c | 59 | ||||
-rw-r--r-- | fs/nilfs2/segbuf.h | 16 | ||||
-rw-r--r-- | fs/nilfs2/segment.c | 19 |
3 files changed, 44 insertions, 50 deletions
diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c index c71b689bdbce..d86056ca9a27 100644 --- a/fs/nilfs2/segbuf.c +++ b/fs/nilfs2/segbuf.c | |||
@@ -63,6 +63,11 @@ struct nilfs_segment_buffer *nilfs_segbuf_new(struct super_block *sb) | |||
63 | INIT_LIST_HEAD(&segbuf->sb_list); | 63 | INIT_LIST_HEAD(&segbuf->sb_list); |
64 | INIT_LIST_HEAD(&segbuf->sb_segsum_buffers); | 64 | INIT_LIST_HEAD(&segbuf->sb_segsum_buffers); |
65 | INIT_LIST_HEAD(&segbuf->sb_payload_buffers); | 65 | INIT_LIST_HEAD(&segbuf->sb_payload_buffers); |
66 | |||
67 | init_completion(&segbuf->sb_bio_event); | ||
68 | atomic_set(&segbuf->sb_err, 0); | ||
69 | segbuf->sb_nbio = 0; | ||
70 | |||
66 | return segbuf; | 71 | return segbuf; |
67 | } | 72 | } |
68 | 73 | ||
@@ -132,8 +137,6 @@ int nilfs_segbuf_reset(struct nilfs_segment_buffer *segbuf, unsigned flags, | |||
132 | segbuf->sb_sum.sumbytes = sizeof(struct nilfs_segment_summary); | 137 | segbuf->sb_sum.sumbytes = sizeof(struct nilfs_segment_summary); |
133 | segbuf->sb_sum.nfinfo = segbuf->sb_sum.nfileblk = 0; | 138 | segbuf->sb_sum.nfinfo = segbuf->sb_sum.nfileblk = 0; |
134 | segbuf->sb_sum.ctime = ctime; | 139 | segbuf->sb_sum.ctime = ctime; |
135 | |||
136 | segbuf->sb_io_error = 0; | ||
137 | return 0; | 140 | return 0; |
138 | } | 141 | } |
139 | 142 | ||
@@ -247,7 +250,7 @@ void nilfs_release_buffers(struct list_head *list) | |||
247 | static void nilfs_end_bio_write(struct bio *bio, int err) | 250 | static void nilfs_end_bio_write(struct bio *bio, int err) |
248 | { | 251 | { |
249 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); | 252 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); |
250 | struct nilfs_write_info *wi = bio->bi_private; | 253 | struct nilfs_segment_buffer *segbuf = bio->bi_private; |
251 | 254 | ||
252 | if (err == -EOPNOTSUPP) { | 255 | if (err == -EOPNOTSUPP) { |
253 | set_bit(BIO_EOPNOTSUPP, &bio->bi_flags); | 256 | set_bit(BIO_EOPNOTSUPP, &bio->bi_flags); |
@@ -256,21 +259,22 @@ static void nilfs_end_bio_write(struct bio *bio, int err) | |||
256 | } | 259 | } |
257 | 260 | ||
258 | if (!uptodate) | 261 | if (!uptodate) |
259 | atomic_inc(&wi->err); | 262 | atomic_inc(&segbuf->sb_err); |
260 | 263 | ||
261 | bio_put(bio); | 264 | bio_put(bio); |
262 | complete(&wi->bio_event); | 265 | complete(&segbuf->sb_bio_event); |
263 | } | 266 | } |
264 | 267 | ||
265 | static int nilfs_submit_seg_bio(struct nilfs_write_info *wi, int mode) | 268 | static int nilfs_segbuf_submit_bio(struct nilfs_segment_buffer *segbuf, |
269 | struct nilfs_write_info *wi, int mode) | ||
266 | { | 270 | { |
267 | struct bio *bio = wi->bio; | 271 | struct bio *bio = wi->bio; |
268 | int err; | 272 | int err; |
269 | 273 | ||
270 | if (wi->nbio > 0 && bdi_write_congested(wi->bdi)) { | 274 | if (segbuf->sb_nbio > 0 && bdi_write_congested(wi->bdi)) { |
271 | wait_for_completion(&wi->bio_event); | 275 | wait_for_completion(&segbuf->sb_bio_event); |
272 | wi->nbio--; | 276 | segbuf->sb_nbio--; |
273 | if (unlikely(atomic_read(&wi->err))) { | 277 | if (unlikely(atomic_read(&segbuf->sb_err))) { |
274 | bio_put(bio); | 278 | bio_put(bio); |
275 | err = -EIO; | 279 | err = -EIO; |
276 | goto failed; | 280 | goto failed; |
@@ -278,7 +282,7 @@ static int nilfs_submit_seg_bio(struct nilfs_write_info *wi, int mode) | |||
278 | } | 282 | } |
279 | 283 | ||
280 | bio->bi_end_io = nilfs_end_bio_write; | 284 | bio->bi_end_io = nilfs_end_bio_write; |
281 | bio->bi_private = wi; | 285 | bio->bi_private = segbuf; |
282 | bio_get(bio); | 286 | bio_get(bio); |
283 | submit_bio(mode, bio); | 287 | submit_bio(mode, bio); |
284 | if (bio_flagged(bio, BIO_EOPNOTSUPP)) { | 288 | if (bio_flagged(bio, BIO_EOPNOTSUPP)) { |
@@ -286,7 +290,7 @@ static int nilfs_submit_seg_bio(struct nilfs_write_info *wi, int mode) | |||
286 | err = -EOPNOTSUPP; | 290 | err = -EOPNOTSUPP; |
287 | goto failed; | 291 | goto failed; |
288 | } | 292 | } |
289 | wi->nbio++; | 293 | segbuf->sb_nbio++; |
290 | bio_put(bio); | 294 | bio_put(bio); |
291 | 295 | ||
292 | wi->bio = NULL; | 296 | wi->bio = NULL; |
@@ -336,15 +340,12 @@ void nilfs_segbuf_prepare_write(struct nilfs_segment_buffer *segbuf, | |||
336 | wi->max_pages = bio_get_nr_vecs(wi->sb->s_bdev); | 340 | wi->max_pages = bio_get_nr_vecs(wi->sb->s_bdev); |
337 | wi->nr_vecs = min(wi->max_pages, wi->rest_blocks); | 341 | wi->nr_vecs = min(wi->max_pages, wi->rest_blocks); |
338 | wi->start = wi->end = 0; | 342 | wi->start = wi->end = 0; |
339 | wi->nbio = 0; | ||
340 | wi->blocknr = segbuf->sb_pseg_start; | 343 | wi->blocknr = segbuf->sb_pseg_start; |
341 | |||
342 | atomic_set(&wi->err, 0); | ||
343 | init_completion(&wi->bio_event); | ||
344 | } | 344 | } |
345 | 345 | ||
346 | static int nilfs_submit_bh(struct nilfs_write_info *wi, struct buffer_head *bh, | 346 | static int nilfs_segbuf_submit_bh(struct nilfs_segment_buffer *segbuf, |
347 | int mode) | 347 | struct nilfs_write_info *wi, |
348 | struct buffer_head *bh, int mode) | ||
348 | { | 349 | { |
349 | int len, err; | 350 | int len, err; |
350 | 351 | ||
@@ -363,7 +364,7 @@ static int nilfs_submit_bh(struct nilfs_write_info *wi, struct buffer_head *bh, | |||
363 | return 0; | 364 | return 0; |
364 | } | 365 | } |
365 | /* bio is FULL */ | 366 | /* bio is FULL */ |
366 | err = nilfs_submit_seg_bio(wi, mode); | 367 | err = nilfs_segbuf_submit_bio(segbuf, wi, mode); |
367 | /* never submit current bh */ | 368 | /* never submit current bh */ |
368 | if (likely(!err)) | 369 | if (likely(!err)) |
369 | goto repeat; | 370 | goto repeat; |
@@ -377,13 +378,13 @@ int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf, | |||
377 | int res = 0, rw = WRITE; | 378 | int res = 0, rw = WRITE; |
378 | 379 | ||
379 | list_for_each_entry(bh, &segbuf->sb_segsum_buffers, b_assoc_buffers) { | 380 | list_for_each_entry(bh, &segbuf->sb_segsum_buffers, b_assoc_buffers) { |
380 | res = nilfs_submit_bh(wi, bh, rw); | 381 | res = nilfs_segbuf_submit_bh(segbuf, wi, bh, rw); |
381 | if (unlikely(res)) | 382 | if (unlikely(res)) |
382 | goto failed_bio; | 383 | goto failed_bio; |
383 | } | 384 | } |
384 | 385 | ||
385 | list_for_each_entry(bh, &segbuf->sb_payload_buffers, b_assoc_buffers) { | 386 | list_for_each_entry(bh, &segbuf->sb_payload_buffers, b_assoc_buffers) { |
386 | res = nilfs_submit_bh(wi, bh, rw); | 387 | res = nilfs_segbuf_submit_bh(segbuf, wi, bh, rw); |
387 | if (unlikely(res)) | 388 | if (unlikely(res)) |
388 | goto failed_bio; | 389 | goto failed_bio; |
389 | } | 390 | } |
@@ -394,7 +395,7 @@ int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf, | |||
394 | * submission. | 395 | * submission. |
395 | */ | 396 | */ |
396 | rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG); | 397 | rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG); |
397 | res = nilfs_submit_seg_bio(wi, rw); | 398 | res = nilfs_segbuf_submit_bio(segbuf, wi, rw); |
398 | } | 399 | } |
399 | 400 | ||
400 | failed_bio: | 401 | failed_bio: |
@@ -403,29 +404,27 @@ int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf, | |||
403 | 404 | ||
404 | /** | 405 | /** |
405 | * nilfs_segbuf_wait - wait for completion of requested BIOs | 406 | * nilfs_segbuf_wait - wait for completion of requested BIOs |
406 | * @wi: nilfs_write_info | 407 | * @segbuf: segment buffer |
407 | * | 408 | * |
408 | * Return Value: On Success, 0 is returned. On Error, one of the following | 409 | * Return Value: On Success, 0 is returned. On Error, one of the following |
409 | * negative error code is returned. | 410 | * negative error code is returned. |
410 | * | 411 | * |
411 | * %-EIO - I/O error | 412 | * %-EIO - I/O error |
412 | */ | 413 | */ |
413 | int nilfs_segbuf_wait(struct nilfs_segment_buffer *segbuf, | 414 | int nilfs_segbuf_wait(struct nilfs_segment_buffer *segbuf) |
414 | struct nilfs_write_info *wi) | ||
415 | { | 415 | { |
416 | int err = 0; | 416 | int err = 0; |
417 | 417 | ||
418 | if (!wi->nbio) | 418 | if (!segbuf->sb_nbio) |
419 | return 0; | 419 | return 0; |
420 | 420 | ||
421 | do { | 421 | do { |
422 | wait_for_completion(&wi->bio_event); | 422 | wait_for_completion(&segbuf->sb_bio_event); |
423 | } while (--wi->nbio > 0); | 423 | } while (--segbuf->sb_nbio > 0); |
424 | 424 | ||
425 | if (unlikely(atomic_read(&wi->err) > 0)) { | 425 | if (unlikely(atomic_read(&segbuf->sb_err) > 0)) { |
426 | printk(KERN_ERR "NILFS: IO error writing segment\n"); | 426 | printk(KERN_ERR "NILFS: IO error writing segment\n"); |
427 | err = -EIO; | 427 | err = -EIO; |
428 | segbuf->sb_io_error = 1; | ||
429 | } | 428 | } |
430 | return err; | 429 | return err; |
431 | } | 430 | } |
diff --git a/fs/nilfs2/segbuf.h b/fs/nilfs2/segbuf.h index 0c3076f4e592..bd076cca37a8 100644 --- a/fs/nilfs2/segbuf.h +++ b/fs/nilfs2/segbuf.h | |||
@@ -77,7 +77,9 @@ struct nilfs_segsum_info { | |||
77 | * @sb_rest_blocks: Number of residual blocks in the current segment | 77 | * @sb_rest_blocks: Number of residual blocks in the current segment |
78 | * @sb_segsum_buffers: List of buffers for segment summaries | 78 | * @sb_segsum_buffers: List of buffers for segment summaries |
79 | * @sb_payload_buffers: List of buffers for segment payload | 79 | * @sb_payload_buffers: List of buffers for segment payload |
80 | * @sb_io_error: I/O error status | 80 | * @sb_nbio: Number of flying bio requests |
81 | * @sb_err: I/O error status | ||
82 | * @sb_bio_event: Completion event of log writing | ||
81 | */ | 83 | */ |
82 | struct nilfs_segment_buffer { | 84 | struct nilfs_segment_buffer { |
83 | struct super_block *sb_super; | 85 | struct super_block *sb_super; |
@@ -96,7 +98,9 @@ struct nilfs_segment_buffer { | |||
96 | struct list_head sb_payload_buffers; /* including super root */ | 98 | struct list_head sb_payload_buffers; /* including super root */ |
97 | 99 | ||
98 | /* io status */ | 100 | /* io status */ |
99 | int sb_io_error; | 101 | int sb_nbio; |
102 | atomic_t sb_err; | ||
103 | struct completion sb_bio_event; | ||
100 | }; | 104 | }; |
101 | 105 | ||
102 | #define NILFS_LIST_SEGBUF(head) \ | 106 | #define NILFS_LIST_SEGBUF(head) \ |
@@ -177,11 +181,6 @@ struct nilfs_write_info { | |||
177 | int nr_vecs; | 181 | int nr_vecs; |
178 | sector_t blocknr; | 182 | sector_t blocknr; |
179 | 183 | ||
180 | int nbio; | ||
181 | atomic_t err; | ||
182 | struct completion bio_event; | ||
183 | /* completion event of segment write */ | ||
184 | |||
185 | /* | 184 | /* |
186 | * The following fields must be set explicitly | 185 | * The following fields must be set explicitly |
187 | */ | 186 | */ |
@@ -195,7 +194,6 @@ void nilfs_segbuf_prepare_write(struct nilfs_segment_buffer *, | |||
195 | struct nilfs_write_info *); | 194 | struct nilfs_write_info *); |
196 | int nilfs_segbuf_write(struct nilfs_segment_buffer *, | 195 | int nilfs_segbuf_write(struct nilfs_segment_buffer *, |
197 | struct nilfs_write_info *); | 196 | struct nilfs_write_info *); |
198 | int nilfs_segbuf_wait(struct nilfs_segment_buffer *, | 197 | int nilfs_segbuf_wait(struct nilfs_segment_buffer *segbuf); |
199 | struct nilfs_write_info *); | ||
200 | 198 | ||
201 | #endif /* _NILFS_SEGBUF_H */ | 199 | #endif /* _NILFS_SEGBUF_H */ |
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 79acf4d66e88..cb004ebe7895 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
@@ -1382,14 +1382,14 @@ static void nilfs_segctor_free_incomplete_segments(struct nilfs_sc_info *sci, | |||
1382 | struct the_nilfs *nilfs) | 1382 | struct the_nilfs *nilfs) |
1383 | { | 1383 | { |
1384 | struct nilfs_segment_buffer *segbuf; | 1384 | struct nilfs_segment_buffer *segbuf; |
1385 | int ret, done = 0; | 1385 | int ret; |
1386 | 1386 | ||
1387 | segbuf = NILFS_FIRST_SEGBUF(&sci->sc_segbufs); | 1387 | segbuf = NILFS_FIRST_SEGBUF(&sci->sc_segbufs); |
1388 | if (nilfs->ns_nextnum != segbuf->sb_nextnum) { | 1388 | if (nilfs->ns_nextnum != segbuf->sb_nextnum) { |
1389 | ret = nilfs_sufile_free(nilfs->ns_sufile, segbuf->sb_nextnum); | 1389 | ret = nilfs_sufile_free(nilfs->ns_sufile, segbuf->sb_nextnum); |
1390 | WARN_ON(ret); /* never fails */ | 1390 | WARN_ON(ret); /* never fails */ |
1391 | } | 1391 | } |
1392 | if (segbuf->sb_io_error) { | 1392 | if (atomic_read(&segbuf->sb_err)) { |
1393 | /* Case 1: The first segment failed */ | 1393 | /* Case 1: The first segment failed */ |
1394 | if (segbuf->sb_pseg_start != segbuf->sb_fseg_start) | 1394 | if (segbuf->sb_pseg_start != segbuf->sb_fseg_start) |
1395 | /* Case 1a: Partial segment appended into an existing | 1395 | /* Case 1a: Partial segment appended into an existing |
@@ -1398,19 +1398,16 @@ static void nilfs_segctor_free_incomplete_segments(struct nilfs_sc_info *sci, | |||
1398 | segbuf->sb_fseg_end); | 1398 | segbuf->sb_fseg_end); |
1399 | else /* Case 1b: New full segment */ | 1399 | else /* Case 1b: New full segment */ |
1400 | set_nilfs_discontinued(nilfs); | 1400 | set_nilfs_discontinued(nilfs); |
1401 | done++; | ||
1402 | } | 1401 | } |
1403 | 1402 | ||
1404 | list_for_each_entry_continue(segbuf, &sci->sc_segbufs, sb_list) { | 1403 | list_for_each_entry_continue(segbuf, &sci->sc_segbufs, sb_list) { |
1405 | ret = nilfs_sufile_free(nilfs->ns_sufile, segbuf->sb_nextnum); | 1404 | ret = nilfs_sufile_free(nilfs->ns_sufile, segbuf->sb_nextnum); |
1406 | WARN_ON(ret); /* never fails */ | 1405 | WARN_ON(ret); /* never fails */ |
1407 | if (!done && segbuf->sb_io_error) { | 1406 | if (atomic_read(&segbuf->sb_err) && |
1408 | if (segbuf->sb_segnum != nilfs->ns_nextnum) | 1407 | segbuf->sb_segnum != nilfs->ns_nextnum) |
1409 | /* Case 2: extended segment (!= next) failed */ | 1408 | /* Case 2: extended segment (!= next) failed */ |
1410 | nilfs_sufile_set_error(nilfs->ns_sufile, | 1409 | nilfs_sufile_set_error(nilfs->ns_sufile, |
1411 | segbuf->sb_segnum); | 1410 | segbuf->sb_segnum); |
1412 | done++; | ||
1413 | } | ||
1414 | } | 1411 | } |
1415 | } | 1412 | } |
1416 | 1413 | ||
@@ -1801,7 +1798,7 @@ static int nilfs_segctor_write(struct nilfs_sc_info *sci, | |||
1801 | nilfs_segbuf_prepare_write(segbuf, &wi); | 1798 | nilfs_segbuf_prepare_write(segbuf, &wi); |
1802 | err = nilfs_segbuf_write(segbuf, &wi); | 1799 | err = nilfs_segbuf_write(segbuf, &wi); |
1803 | 1800 | ||
1804 | res = nilfs_segbuf_wait(segbuf, &wi); | 1801 | res = nilfs_segbuf_wait(segbuf); |
1805 | err = err ? : res; | 1802 | err = err ? : res; |
1806 | if (err) | 1803 | if (err) |
1807 | return err; | 1804 | return err; |