aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nilfs2')
-rw-r--r--fs/nilfs2/segbuf.c59
-rw-r--r--fs/nilfs2/segbuf.h16
-rw-r--r--fs/nilfs2/segment.c19
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)
247static void nilfs_end_bio_write(struct bio *bio, int err) 250static 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
265static int nilfs_submit_seg_bio(struct nilfs_write_info *wi, int mode) 268static 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
346static int nilfs_submit_bh(struct nilfs_write_info *wi, struct buffer_head *bh, 346static 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 */
413int nilfs_segbuf_wait(struct nilfs_segment_buffer *segbuf, 414int 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 */
82struct nilfs_segment_buffer { 84struct 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 *);
196int nilfs_segbuf_write(struct nilfs_segment_buffer *, 195int nilfs_segbuf_write(struct nilfs_segment_buffer *,
197 struct nilfs_write_info *); 196 struct nilfs_write_info *);
198int nilfs_segbuf_wait(struct nilfs_segment_buffer *, 197int 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;