diff options
Diffstat (limited to 'fs/nilfs2/segment.c')
| -rw-r--r-- | fs/nilfs2/segment.c | 369 |
1 files changed, 178 insertions, 191 deletions
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 6eff66a070d5..17584c524486 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
| @@ -974,12 +974,12 @@ static void nilfs_segctor_fill_in_super_root(struct nilfs_sc_info *sci, | |||
| 974 | nilfs->ns_nongc_ctime : sci->sc_seg_ctime); | 974 | nilfs->ns_nongc_ctime : sci->sc_seg_ctime); |
| 975 | raw_sr->sr_flags = 0; | 975 | raw_sr->sr_flags = 0; |
| 976 | 976 | ||
| 977 | nilfs_mdt_write_inode_direct( | 977 | nilfs_write_inode_common(nilfs_dat_inode(nilfs), (void *)raw_sr + |
| 978 | nilfs_dat_inode(nilfs), bh_sr, NILFS_SR_DAT_OFFSET(isz)); | 978 | NILFS_SR_DAT_OFFSET(isz), 1); |
| 979 | nilfs_mdt_write_inode_direct( | 979 | nilfs_write_inode_common(nilfs->ns_cpfile, (void *)raw_sr + |
| 980 | nilfs->ns_cpfile, bh_sr, NILFS_SR_CPFILE_OFFSET(isz)); | 980 | NILFS_SR_CPFILE_OFFSET(isz), 1); |
| 981 | nilfs_mdt_write_inode_direct( | 981 | nilfs_write_inode_common(nilfs->ns_sufile, (void *)raw_sr + |
| 982 | nilfs->ns_sufile, bh_sr, NILFS_SR_SUFILE_OFFSET(isz)); | 982 | NILFS_SR_SUFILE_OFFSET(isz), 1); |
| 983 | } | 983 | } |
| 984 | 984 | ||
| 985 | static void nilfs_redirty_inodes(struct list_head *head) | 985 | static void nilfs_redirty_inodes(struct list_head *head) |
| @@ -1273,73 +1273,75 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode) | |||
| 1273 | return err; | 1273 | return err; |
| 1274 | } | 1274 | } |
| 1275 | 1275 | ||
| 1276 | static int nilfs_touch_segusage(struct inode *sufile, __u64 segnum) | 1276 | /** |
| 1277 | { | 1277 | * nilfs_segctor_begin_construction - setup segment buffer to make a new log |
| 1278 | struct buffer_head *bh_su; | 1278 | * @sci: nilfs_sc_info |
| 1279 | struct nilfs_segment_usage *raw_su; | 1279 | * @nilfs: nilfs object |
| 1280 | int err; | 1280 | */ |
| 1281 | |||
| 1282 | err = nilfs_sufile_get_segment_usage(sufile, segnum, &raw_su, &bh_su); | ||
| 1283 | if (unlikely(err)) | ||
| 1284 | return err; | ||
| 1285 | nilfs_mdt_mark_buffer_dirty(bh_su); | ||
| 1286 | nilfs_mdt_mark_dirty(sufile); | ||
| 1287 | nilfs_sufile_put_segment_usage(sufile, segnum, bh_su); | ||
| 1288 | return 0; | ||
| 1289 | } | ||
| 1290 | |||
| 1291 | static int nilfs_segctor_begin_construction(struct nilfs_sc_info *sci, | 1281 | static int nilfs_segctor_begin_construction(struct nilfs_sc_info *sci, |
| 1292 | struct the_nilfs *nilfs) | 1282 | struct the_nilfs *nilfs) |
| 1293 | { | 1283 | { |
| 1294 | struct nilfs_segment_buffer *segbuf, *n; | 1284 | struct nilfs_segment_buffer *segbuf, *prev; |
| 1295 | __u64 nextnum; | 1285 | __u64 nextnum; |
| 1296 | int err; | 1286 | int err, alloc = 0; |
| 1297 | 1287 | ||
| 1298 | if (list_empty(&sci->sc_segbufs)) { | 1288 | segbuf = nilfs_segbuf_new(sci->sc_super); |
| 1299 | segbuf = nilfs_segbuf_new(sci->sc_super); | 1289 | if (unlikely(!segbuf)) |
| 1300 | if (unlikely(!segbuf)) | 1290 | return -ENOMEM; |
| 1301 | return -ENOMEM; | 1291 | |
| 1302 | list_add(&segbuf->sb_list, &sci->sc_segbufs); | 1292 | if (list_empty(&sci->sc_write_logs)) { |
| 1303 | } else | 1293 | nilfs_segbuf_map(segbuf, nilfs->ns_segnum, |
| 1304 | segbuf = NILFS_FIRST_SEGBUF(&sci->sc_segbufs); | 1294 | nilfs->ns_pseg_offset, nilfs); |
| 1295 | if (segbuf->sb_rest_blocks < NILFS_PSEG_MIN_BLOCKS) { | ||
| 1296 | nilfs_shift_to_next_segment(nilfs); | ||
| 1297 | nilfs_segbuf_map(segbuf, nilfs->ns_segnum, 0, nilfs); | ||
| 1298 | } | ||
| 1305 | 1299 | ||
| 1306 | nilfs_segbuf_map(segbuf, nilfs->ns_segnum, nilfs->ns_pseg_offset, | 1300 | segbuf->sb_sum.seg_seq = nilfs->ns_seg_seq; |
| 1307 | nilfs); | 1301 | nextnum = nilfs->ns_nextnum; |
| 1308 | 1302 | ||
| 1309 | if (segbuf->sb_rest_blocks < NILFS_PSEG_MIN_BLOCKS) { | 1303 | if (nilfs->ns_segnum == nilfs->ns_nextnum) |
| 1310 | nilfs_shift_to_next_segment(nilfs); | 1304 | /* Start from the head of a new full segment */ |
| 1311 | nilfs_segbuf_map(segbuf, nilfs->ns_segnum, 0, nilfs); | 1305 | alloc++; |
| 1306 | } else { | ||
| 1307 | /* Continue logs */ | ||
| 1308 | prev = NILFS_LAST_SEGBUF(&sci->sc_write_logs); | ||
| 1309 | nilfs_segbuf_map_cont(segbuf, prev); | ||
| 1310 | segbuf->sb_sum.seg_seq = prev->sb_sum.seg_seq; | ||
| 1311 | nextnum = prev->sb_nextnum; | ||
| 1312 | |||
| 1313 | if (segbuf->sb_rest_blocks < NILFS_PSEG_MIN_BLOCKS) { | ||
| 1314 | nilfs_segbuf_map(segbuf, prev->sb_nextnum, 0, nilfs); | ||
| 1315 | segbuf->sb_sum.seg_seq++; | ||
| 1316 | alloc++; | ||
| 1317 | } | ||
| 1312 | } | 1318 | } |
| 1313 | sci->sc_segbuf_nblocks = segbuf->sb_rest_blocks; | ||
| 1314 | 1319 | ||
| 1315 | err = nilfs_touch_segusage(nilfs->ns_sufile, segbuf->sb_segnum); | 1320 | err = nilfs_sufile_mark_dirty(nilfs->ns_sufile, segbuf->sb_segnum); |
| 1316 | if (unlikely(err)) | 1321 | if (err) |
| 1317 | return err; | 1322 | goto failed; |
| 1318 | 1323 | ||
| 1319 | if (nilfs->ns_segnum == nilfs->ns_nextnum) { | 1324 | if (alloc) { |
| 1320 | /* Start from the head of a new full segment */ | ||
| 1321 | err = nilfs_sufile_alloc(nilfs->ns_sufile, &nextnum); | 1325 | err = nilfs_sufile_alloc(nilfs->ns_sufile, &nextnum); |
| 1322 | if (unlikely(err)) | 1326 | if (err) |
| 1323 | return err; | 1327 | goto failed; |
| 1324 | } else | 1328 | } |
| 1325 | nextnum = nilfs->ns_nextnum; | ||
| 1326 | |||
| 1327 | segbuf->sb_sum.seg_seq = nilfs->ns_seg_seq; | ||
| 1328 | nilfs_segbuf_set_next_segnum(segbuf, nextnum, nilfs); | 1329 | nilfs_segbuf_set_next_segnum(segbuf, nextnum, nilfs); |
| 1329 | 1330 | ||
| 1330 | /* truncating segment buffers */ | 1331 | BUG_ON(!list_empty(&sci->sc_segbufs)); |
| 1331 | list_for_each_entry_safe_continue(segbuf, n, &sci->sc_segbufs, | 1332 | list_add_tail(&segbuf->sb_list, &sci->sc_segbufs); |
| 1332 | sb_list) { | 1333 | sci->sc_segbuf_nblocks = segbuf->sb_rest_blocks; |
| 1333 | list_del_init(&segbuf->sb_list); | ||
| 1334 | nilfs_segbuf_free(segbuf); | ||
| 1335 | } | ||
| 1336 | return 0; | 1334 | return 0; |
| 1335 | |||
| 1336 | failed: | ||
| 1337 | nilfs_segbuf_free(segbuf); | ||
| 1338 | return err; | ||
| 1337 | } | 1339 | } |
| 1338 | 1340 | ||
| 1339 | static int nilfs_segctor_extend_segments(struct nilfs_sc_info *sci, | 1341 | static int nilfs_segctor_extend_segments(struct nilfs_sc_info *sci, |
| 1340 | struct the_nilfs *nilfs, int nadd) | 1342 | struct the_nilfs *nilfs, int nadd) |
| 1341 | { | 1343 | { |
| 1342 | struct nilfs_segment_buffer *segbuf, *prev, *n; | 1344 | struct nilfs_segment_buffer *segbuf, *prev; |
| 1343 | struct inode *sufile = nilfs->ns_sufile; | 1345 | struct inode *sufile = nilfs->ns_sufile; |
| 1344 | __u64 nextnextnum; | 1346 | __u64 nextnextnum; |
| 1345 | LIST_HEAD(list); | 1347 | LIST_HEAD(list); |
| @@ -1352,7 +1354,7 @@ static int nilfs_segctor_extend_segments(struct nilfs_sc_info *sci, | |||
| 1352 | * not be dirty. The following call ensures that the buffer is dirty | 1354 | * not be dirty. The following call ensures that the buffer is dirty |
| 1353 | * and will pin the buffer on memory until the sufile is written. | 1355 | * and will pin the buffer on memory until the sufile is written. |
| 1354 | */ | 1356 | */ |
| 1355 | err = nilfs_touch_segusage(sufile, prev->sb_nextnum); | 1357 | err = nilfs_sufile_mark_dirty(sufile, prev->sb_nextnum); |
| 1356 | if (unlikely(err)) | 1358 | if (unlikely(err)) |
| 1357 | return err; | 1359 | return err; |
| 1358 | 1360 | ||
| @@ -1378,33 +1380,33 @@ static int nilfs_segctor_extend_segments(struct nilfs_sc_info *sci, | |||
| 1378 | list_add_tail(&segbuf->sb_list, &list); | 1380 | list_add_tail(&segbuf->sb_list, &list); |
| 1379 | prev = segbuf; | 1381 | prev = segbuf; |
| 1380 | } | 1382 | } |
| 1381 | list_splice(&list, sci->sc_segbufs.prev); | 1383 | list_splice_tail(&list, &sci->sc_segbufs); |
| 1382 | return 0; | 1384 | return 0; |
| 1383 | 1385 | ||
| 1384 | failed_segbuf: | 1386 | failed_segbuf: |
| 1385 | nilfs_segbuf_free(segbuf); | 1387 | nilfs_segbuf_free(segbuf); |
| 1386 | failed: | 1388 | failed: |
| 1387 | list_for_each_entry_safe(segbuf, n, &list, sb_list) { | 1389 | list_for_each_entry(segbuf, &list, sb_list) { |
| 1388 | ret = nilfs_sufile_free(sufile, segbuf->sb_nextnum); | 1390 | ret = nilfs_sufile_free(sufile, segbuf->sb_nextnum); |
| 1389 | WARN_ON(ret); /* never fails */ | 1391 | WARN_ON(ret); /* never fails */ |
| 1390 | list_del_init(&segbuf->sb_list); | ||
| 1391 | nilfs_segbuf_free(segbuf); | ||
| 1392 | } | 1392 | } |
| 1393 | nilfs_destroy_logs(&list); | ||
| 1393 | return err; | 1394 | return err; |
| 1394 | } | 1395 | } |
| 1395 | 1396 | ||
| 1396 | static void nilfs_segctor_free_incomplete_segments(struct nilfs_sc_info *sci, | 1397 | static void nilfs_free_incomplete_logs(struct list_head *logs, |
| 1397 | struct the_nilfs *nilfs) | 1398 | struct the_nilfs *nilfs) |
| 1398 | { | 1399 | { |
| 1399 | struct nilfs_segment_buffer *segbuf; | 1400 | struct nilfs_segment_buffer *segbuf, *prev; |
| 1400 | int ret, done = 0; | 1401 | struct inode *sufile = nilfs->ns_sufile; |
| 1402 | int ret; | ||
| 1401 | 1403 | ||
| 1402 | segbuf = NILFS_FIRST_SEGBUF(&sci->sc_segbufs); | 1404 | segbuf = NILFS_FIRST_SEGBUF(logs); |
| 1403 | if (nilfs->ns_nextnum != segbuf->sb_nextnum) { | 1405 | if (nilfs->ns_nextnum != segbuf->sb_nextnum) { |
| 1404 | ret = nilfs_sufile_free(nilfs->ns_sufile, segbuf->sb_nextnum); | 1406 | ret = nilfs_sufile_free(sufile, segbuf->sb_nextnum); |
| 1405 | WARN_ON(ret); /* never fails */ | 1407 | WARN_ON(ret); /* never fails */ |
| 1406 | } | 1408 | } |
| 1407 | if (segbuf->sb_io_error) { | 1409 | if (atomic_read(&segbuf->sb_err)) { |
| 1408 | /* Case 1: The first segment failed */ | 1410 | /* Case 1: The first segment failed */ |
| 1409 | if (segbuf->sb_pseg_start != segbuf->sb_fseg_start) | 1411 | if (segbuf->sb_pseg_start != segbuf->sb_fseg_start) |
| 1410 | /* Case 1a: Partial segment appended into an existing | 1412 | /* Case 1a: Partial segment appended into an existing |
| @@ -1413,106 +1415,54 @@ static void nilfs_segctor_free_incomplete_segments(struct nilfs_sc_info *sci, | |||
| 1413 | segbuf->sb_fseg_end); | 1415 | segbuf->sb_fseg_end); |
| 1414 | else /* Case 1b: New full segment */ | 1416 | else /* Case 1b: New full segment */ |
| 1415 | set_nilfs_discontinued(nilfs); | 1417 | set_nilfs_discontinued(nilfs); |
| 1416 | done++; | ||
| 1417 | } | 1418 | } |
| 1418 | 1419 | ||
| 1419 | list_for_each_entry_continue(segbuf, &sci->sc_segbufs, sb_list) { | 1420 | prev = segbuf; |
| 1420 | ret = nilfs_sufile_free(nilfs->ns_sufile, segbuf->sb_nextnum); | 1421 | list_for_each_entry_continue(segbuf, logs, sb_list) { |
| 1421 | WARN_ON(ret); /* never fails */ | 1422 | if (prev->sb_nextnum != segbuf->sb_nextnum) { |
| 1422 | if (!done && segbuf->sb_io_error) { | 1423 | ret = nilfs_sufile_free(sufile, segbuf->sb_nextnum); |
| 1423 | if (segbuf->sb_segnum != nilfs->ns_nextnum) | 1424 | WARN_ON(ret); /* never fails */ |
| 1424 | /* Case 2: extended segment (!= next) failed */ | ||
| 1425 | nilfs_sufile_set_error(nilfs->ns_sufile, | ||
| 1426 | segbuf->sb_segnum); | ||
| 1427 | done++; | ||
| 1428 | } | ||
| 1429 | } | ||
| 1430 | } | ||
| 1431 | |||
| 1432 | static void nilfs_segctor_clear_segment_buffers(struct nilfs_sc_info *sci) | ||
| 1433 | { | ||
| 1434 | struct nilfs_segment_buffer *segbuf; | ||
| 1435 | |||
| 1436 | list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) | ||
| 1437 | nilfs_segbuf_clear(segbuf); | ||
| 1438 | sci->sc_super_root = NULL; | ||
| 1439 | } | ||
| 1440 | |||
| 1441 | static void nilfs_segctor_destroy_segment_buffers(struct nilfs_sc_info *sci) | ||
| 1442 | { | ||
| 1443 | struct nilfs_segment_buffer *segbuf; | ||
| 1444 | |||
| 1445 | while (!list_empty(&sci->sc_segbufs)) { | ||
| 1446 | segbuf = NILFS_FIRST_SEGBUF(&sci->sc_segbufs); | ||
| 1447 | list_del_init(&segbuf->sb_list); | ||
| 1448 | nilfs_segbuf_free(segbuf); | ||
| 1449 | } | ||
| 1450 | /* sci->sc_curseg = NULL; */ | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | static void nilfs_segctor_end_construction(struct nilfs_sc_info *sci, | ||
| 1454 | struct the_nilfs *nilfs, int err) | ||
| 1455 | { | ||
| 1456 | if (unlikely(err)) { | ||
| 1457 | nilfs_segctor_free_incomplete_segments(sci, nilfs); | ||
| 1458 | if (sci->sc_stage.flags & NILFS_CF_SUFREED) { | ||
| 1459 | int ret; | ||
| 1460 | |||
| 1461 | ret = nilfs_sufile_cancel_freev(nilfs->ns_sufile, | ||
| 1462 | sci->sc_freesegs, | ||
| 1463 | sci->sc_nfreesegs, | ||
| 1464 | NULL); | ||
| 1465 | WARN_ON(ret); /* do not happen */ | ||
| 1466 | } | 1425 | } |
| 1426 | if (atomic_read(&segbuf->sb_err) && | ||
| 1427 | segbuf->sb_segnum != nilfs->ns_nextnum) | ||
| 1428 | /* Case 2: extended segment (!= next) failed */ | ||
| 1429 | nilfs_sufile_set_error(sufile, segbuf->sb_segnum); | ||
| 1430 | prev = segbuf; | ||
| 1467 | } | 1431 | } |
| 1468 | nilfs_segctor_clear_segment_buffers(sci); | ||
| 1469 | } | 1432 | } |
| 1470 | 1433 | ||
| 1471 | static void nilfs_segctor_update_segusage(struct nilfs_sc_info *sci, | 1434 | static void nilfs_segctor_update_segusage(struct nilfs_sc_info *sci, |
| 1472 | struct inode *sufile) | 1435 | struct inode *sufile) |
| 1473 | { | 1436 | { |
| 1474 | struct nilfs_segment_buffer *segbuf; | 1437 | struct nilfs_segment_buffer *segbuf; |
| 1475 | struct buffer_head *bh_su; | ||
| 1476 | struct nilfs_segment_usage *raw_su; | ||
| 1477 | unsigned long live_blocks; | 1438 | unsigned long live_blocks; |
| 1478 | int ret; | 1439 | int ret; |
| 1479 | 1440 | ||
| 1480 | list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) { | 1441 | list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) { |
| 1481 | ret = nilfs_sufile_get_segment_usage(sufile, segbuf->sb_segnum, | ||
| 1482 | &raw_su, &bh_su); | ||
| 1483 | WARN_ON(ret); /* always succeed because bh_su is dirty */ | ||
| 1484 | live_blocks = segbuf->sb_sum.nblocks + | 1442 | live_blocks = segbuf->sb_sum.nblocks + |
| 1485 | (segbuf->sb_pseg_start - segbuf->sb_fseg_start); | 1443 | (segbuf->sb_pseg_start - segbuf->sb_fseg_start); |
| 1486 | raw_su->su_lastmod = cpu_to_le64(sci->sc_seg_ctime); | 1444 | ret = nilfs_sufile_set_segment_usage(sufile, segbuf->sb_segnum, |
| 1487 | raw_su->su_nblocks = cpu_to_le32(live_blocks); | 1445 | live_blocks, |
| 1488 | nilfs_sufile_put_segment_usage(sufile, segbuf->sb_segnum, | 1446 | sci->sc_seg_ctime); |
| 1489 | bh_su); | 1447 | WARN_ON(ret); /* always succeed because the segusage is dirty */ |
| 1490 | } | 1448 | } |
| 1491 | } | 1449 | } |
| 1492 | 1450 | ||
| 1493 | static void nilfs_segctor_cancel_segusage(struct nilfs_sc_info *sci, | 1451 | static void nilfs_cancel_segusage(struct list_head *logs, struct inode *sufile) |
| 1494 | struct inode *sufile) | ||
| 1495 | { | 1452 | { |
| 1496 | struct nilfs_segment_buffer *segbuf; | 1453 | struct nilfs_segment_buffer *segbuf; |
| 1497 | struct buffer_head *bh_su; | ||
| 1498 | struct nilfs_segment_usage *raw_su; | ||
| 1499 | int ret; | 1454 | int ret; |
| 1500 | 1455 | ||
| 1501 | segbuf = NILFS_FIRST_SEGBUF(&sci->sc_segbufs); | 1456 | segbuf = NILFS_FIRST_SEGBUF(logs); |
| 1502 | ret = nilfs_sufile_get_segment_usage(sufile, segbuf->sb_segnum, | 1457 | ret = nilfs_sufile_set_segment_usage(sufile, segbuf->sb_segnum, |
| 1503 | &raw_su, &bh_su); | 1458 | segbuf->sb_pseg_start - |
| 1504 | WARN_ON(ret); /* always succeed because bh_su is dirty */ | 1459 | segbuf->sb_fseg_start, 0); |
| 1505 | raw_su->su_nblocks = cpu_to_le32(segbuf->sb_pseg_start - | 1460 | WARN_ON(ret); /* always succeed because the segusage is dirty */ |
| 1506 | segbuf->sb_fseg_start); | ||
| 1507 | nilfs_sufile_put_segment_usage(sufile, segbuf->sb_segnum, bh_su); | ||
| 1508 | 1461 | ||
| 1509 | list_for_each_entry_continue(segbuf, &sci->sc_segbufs, sb_list) { | 1462 | list_for_each_entry_continue(segbuf, logs, sb_list) { |
| 1510 | ret = nilfs_sufile_get_segment_usage(sufile, segbuf->sb_segnum, | 1463 | ret = nilfs_sufile_set_segment_usage(sufile, segbuf->sb_segnum, |
| 1511 | &raw_su, &bh_su); | 1464 | 0, 0); |
| 1512 | WARN_ON(ret); /* always succeed */ | 1465 | WARN_ON(ret); /* always succeed */ |
| 1513 | raw_su->su_nblocks = 0; | ||
| 1514 | nilfs_sufile_put_segment_usage(sufile, segbuf->sb_segnum, | ||
| 1515 | bh_su); | ||
| 1516 | } | 1466 | } |
| 1517 | } | 1467 | } |
| 1518 | 1468 | ||
| @@ -1520,17 +1470,15 @@ static void nilfs_segctor_truncate_segments(struct nilfs_sc_info *sci, | |||
| 1520 | struct nilfs_segment_buffer *last, | 1470 | struct nilfs_segment_buffer *last, |
| 1521 | struct inode *sufile) | 1471 | struct inode *sufile) |
| 1522 | { | 1472 | { |
| 1523 | struct nilfs_segment_buffer *segbuf = last, *n; | 1473 | struct nilfs_segment_buffer *segbuf = last; |
| 1524 | int ret; | 1474 | int ret; |
| 1525 | 1475 | ||
| 1526 | list_for_each_entry_safe_continue(segbuf, n, &sci->sc_segbufs, | 1476 | list_for_each_entry_continue(segbuf, &sci->sc_segbufs, sb_list) { |
| 1527 | sb_list) { | ||
| 1528 | list_del_init(&segbuf->sb_list); | ||
| 1529 | sci->sc_segbuf_nblocks -= segbuf->sb_rest_blocks; | 1477 | sci->sc_segbuf_nblocks -= segbuf->sb_rest_blocks; |
| 1530 | ret = nilfs_sufile_free(sufile, segbuf->sb_nextnum); | 1478 | ret = nilfs_sufile_free(sufile, segbuf->sb_nextnum); |
| 1531 | WARN_ON(ret); | 1479 | WARN_ON(ret); |
| 1532 | nilfs_segbuf_free(segbuf); | ||
| 1533 | } | 1480 | } |
| 1481 | nilfs_truncate_logs(&sci->sc_segbufs, last); | ||
| 1534 | } | 1482 | } |
| 1535 | 1483 | ||
| 1536 | 1484 | ||
| @@ -1569,7 +1517,7 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci, | |||
| 1569 | NULL); | 1517 | NULL); |
| 1570 | WARN_ON(err); /* do not happen */ | 1518 | WARN_ON(err); /* do not happen */ |
| 1571 | } | 1519 | } |
| 1572 | nilfs_segctor_clear_segment_buffers(sci); | 1520 | nilfs_clear_logs(&sci->sc_segbufs); |
| 1573 | 1521 | ||
| 1574 | err = nilfs_segctor_extend_segments(sci, nilfs, nadd); | 1522 | err = nilfs_segctor_extend_segments(sci, nilfs, nadd); |
| 1575 | if (unlikely(err)) | 1523 | if (unlikely(err)) |
| @@ -1814,26 +1762,18 @@ static int nilfs_segctor_prepare_write(struct nilfs_sc_info *sci, | |||
| 1814 | } | 1762 | } |
| 1815 | 1763 | ||
| 1816 | static int nilfs_segctor_write(struct nilfs_sc_info *sci, | 1764 | static int nilfs_segctor_write(struct nilfs_sc_info *sci, |
| 1817 | struct backing_dev_info *bdi) | 1765 | struct the_nilfs *nilfs) |
| 1818 | { | 1766 | { |
| 1819 | struct nilfs_segment_buffer *segbuf; | 1767 | struct nilfs_segment_buffer *segbuf; |
| 1820 | struct nilfs_write_info wi; | 1768 | int ret = 0; |
| 1821 | int err, res; | ||
| 1822 | |||
| 1823 | wi.sb = sci->sc_super; | ||
| 1824 | wi.bh_sr = sci->sc_super_root; | ||
| 1825 | wi.bdi = bdi; | ||
| 1826 | 1769 | ||
| 1827 | list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) { | 1770 | list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) { |
| 1828 | nilfs_segbuf_prepare_write(segbuf, &wi); | 1771 | ret = nilfs_segbuf_write(segbuf, nilfs); |
| 1829 | err = nilfs_segbuf_write(segbuf, &wi); | 1772 | if (ret) |
| 1830 | 1773 | break; | |
| 1831 | res = nilfs_segbuf_wait(segbuf, &wi); | ||
| 1832 | err = err ? : res; | ||
| 1833 | if (err) | ||
| 1834 | return err; | ||
| 1835 | } | 1774 | } |
| 1836 | return 0; | 1775 | list_splice_tail_init(&sci->sc_segbufs, &sci->sc_write_logs); |
| 1776 | return ret; | ||
| 1837 | } | 1777 | } |
| 1838 | 1778 | ||
| 1839 | static void __nilfs_end_page_io(struct page *page, int err) | 1779 | static void __nilfs_end_page_io(struct page *page, int err) |
| @@ -1911,15 +1851,17 @@ static void nilfs_clear_copied_buffers(struct list_head *list, int err) | |||
| 1911 | } | 1851 | } |
| 1912 | } | 1852 | } |
| 1913 | 1853 | ||
| 1914 | static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci, | 1854 | static void nilfs_abort_logs(struct list_head *logs, struct page *failed_page, |
| 1915 | struct page *failed_page, int err) | 1855 | struct buffer_head *bh_sr, int err) |
| 1916 | { | 1856 | { |
| 1917 | struct nilfs_segment_buffer *segbuf; | 1857 | struct nilfs_segment_buffer *segbuf; |
| 1918 | struct page *bd_page = NULL, *fs_page = NULL; | 1858 | struct page *bd_page = NULL, *fs_page = NULL; |
| 1859 | struct buffer_head *bh; | ||
| 1919 | 1860 | ||
| 1920 | list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) { | 1861 | if (list_empty(logs)) |
| 1921 | struct buffer_head *bh; | 1862 | return; |
| 1922 | 1863 | ||
| 1864 | list_for_each_entry(segbuf, logs, sb_list) { | ||
| 1923 | list_for_each_entry(bh, &segbuf->sb_segsum_buffers, | 1865 | list_for_each_entry(bh, &segbuf->sb_segsum_buffers, |
| 1924 | b_assoc_buffers) { | 1866 | b_assoc_buffers) { |
| 1925 | if (bh->b_page != bd_page) { | 1867 | if (bh->b_page != bd_page) { |
| @@ -1931,7 +1873,7 @@ static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci, | |||
| 1931 | 1873 | ||
| 1932 | list_for_each_entry(bh, &segbuf->sb_payload_buffers, | 1874 | list_for_each_entry(bh, &segbuf->sb_payload_buffers, |
| 1933 | b_assoc_buffers) { | 1875 | b_assoc_buffers) { |
| 1934 | if (bh == sci->sc_super_root) { | 1876 | if (bh == bh_sr) { |
| 1935 | if (bh->b_page != bd_page) { | 1877 | if (bh->b_page != bd_page) { |
| 1936 | end_page_writeback(bd_page); | 1878 | end_page_writeback(bd_page); |
| 1937 | bd_page = bh->b_page; | 1879 | bd_page = bh->b_page; |
| @@ -1941,7 +1883,7 @@ static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci, | |||
| 1941 | if (bh->b_page != fs_page) { | 1883 | if (bh->b_page != fs_page) { |
| 1942 | nilfs_end_page_io(fs_page, err); | 1884 | nilfs_end_page_io(fs_page, err); |
| 1943 | if (fs_page && fs_page == failed_page) | 1885 | if (fs_page && fs_page == failed_page) |
| 1944 | goto done; | 1886 | return; |
| 1945 | fs_page = bh->b_page; | 1887 | fs_page = bh->b_page; |
| 1946 | } | 1888 | } |
| 1947 | } | 1889 | } |
| @@ -1950,8 +1892,34 @@ static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci, | |||
| 1950 | end_page_writeback(bd_page); | 1892 | end_page_writeback(bd_page); |
| 1951 | 1893 | ||
| 1952 | nilfs_end_page_io(fs_page, err); | 1894 | nilfs_end_page_io(fs_page, err); |
| 1953 | done: | 1895 | } |
| 1896 | |||
| 1897 | static void nilfs_segctor_abort_construction(struct nilfs_sc_info *sci, | ||
| 1898 | struct the_nilfs *nilfs, int err) | ||
| 1899 | { | ||
| 1900 | LIST_HEAD(logs); | ||
| 1901 | int ret; | ||
| 1902 | |||
| 1903 | list_splice_tail_init(&sci->sc_write_logs, &logs); | ||
| 1904 | ret = nilfs_wait_on_logs(&logs); | ||
| 1905 | if (ret) | ||
| 1906 | nilfs_abort_logs(&logs, NULL, sci->sc_super_root, ret); | ||
| 1907 | |||
| 1908 | list_splice_tail_init(&sci->sc_segbufs, &logs); | ||
| 1909 | nilfs_cancel_segusage(&logs, nilfs->ns_sufile); | ||
| 1910 | nilfs_free_incomplete_logs(&logs, nilfs); | ||
| 1954 | nilfs_clear_copied_buffers(&sci->sc_copied_buffers, err); | 1911 | nilfs_clear_copied_buffers(&sci->sc_copied_buffers, err); |
| 1912 | |||
| 1913 | if (sci->sc_stage.flags & NILFS_CF_SUFREED) { | ||
| 1914 | ret = nilfs_sufile_cancel_freev(nilfs->ns_sufile, | ||
| 1915 | sci->sc_freesegs, | ||
| 1916 | sci->sc_nfreesegs, | ||
| 1917 | NULL); | ||
| 1918 | WARN_ON(ret); /* do not happen */ | ||
| 1919 | } | ||
| 1920 | |||
| 1921 | nilfs_destroy_logs(&logs); | ||
| 1922 | sci->sc_super_root = NULL; | ||
| 1955 | } | 1923 | } |
| 1956 | 1924 | ||
| 1957 | static void nilfs_set_next_segment(struct the_nilfs *nilfs, | 1925 | static void nilfs_set_next_segment(struct the_nilfs *nilfs, |
| @@ -1973,7 +1941,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) | |||
| 1973 | struct the_nilfs *nilfs = sbi->s_nilfs; | 1941 | struct the_nilfs *nilfs = sbi->s_nilfs; |
| 1974 | int update_sr = (sci->sc_super_root != NULL); | 1942 | int update_sr = (sci->sc_super_root != NULL); |
| 1975 | 1943 | ||
| 1976 | list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) { | 1944 | list_for_each_entry(segbuf, &sci->sc_write_logs, sb_list) { |
| 1977 | struct buffer_head *bh; | 1945 | struct buffer_head *bh; |
| 1978 | 1946 | ||
| 1979 | list_for_each_entry(bh, &segbuf->sb_segsum_buffers, | 1947 | list_for_each_entry(bh, &segbuf->sb_segsum_buffers, |
| @@ -2046,7 +2014,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) | |||
| 2046 | 2014 | ||
| 2047 | sci->sc_nblk_inc += sci->sc_nblk_this_inc; | 2015 | sci->sc_nblk_inc += sci->sc_nblk_this_inc; |
| 2048 | 2016 | ||
| 2049 | segbuf = NILFS_LAST_SEGBUF(&sci->sc_segbufs); | 2017 | segbuf = NILFS_LAST_SEGBUF(&sci->sc_write_logs); |
| 2050 | nilfs_set_next_segment(nilfs, segbuf); | 2018 | nilfs_set_next_segment(nilfs, segbuf); |
| 2051 | 2019 | ||
| 2052 | if (update_sr) { | 2020 | if (update_sr) { |
| @@ -2057,10 +2025,23 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) | |||
| 2057 | clear_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags); | 2025 | clear_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags); |
| 2058 | clear_bit(NILFS_SC_DIRTY, &sci->sc_flags); | 2026 | clear_bit(NILFS_SC_DIRTY, &sci->sc_flags); |
| 2059 | set_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags); | 2027 | set_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags); |
| 2028 | nilfs_segctor_clear_metadata_dirty(sci); | ||
| 2060 | } else | 2029 | } else |
| 2061 | clear_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags); | 2030 | clear_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags); |
| 2062 | } | 2031 | } |
| 2063 | 2032 | ||
| 2033 | static int nilfs_segctor_wait(struct nilfs_sc_info *sci) | ||
| 2034 | { | ||
| 2035 | int ret; | ||
| 2036 | |||
| 2037 | ret = nilfs_wait_on_logs(&sci->sc_write_logs); | ||
| 2038 | if (!ret) { | ||
| 2039 | nilfs_segctor_complete_write(sci); | ||
| 2040 | nilfs_destroy_logs(&sci->sc_write_logs); | ||
| 2041 | } | ||
| 2042 | return ret; | ||
| 2043 | } | ||
| 2044 | |||
| 2064 | static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, | 2045 | static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, |
| 2065 | struct nilfs_sb_info *sbi) | 2046 | struct nilfs_sb_info *sbi) |
| 2066 | { | 2047 | { |
| @@ -2173,7 +2154,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) | |||
| 2173 | /* Avoid empty segment */ | 2154 | /* Avoid empty segment */ |
| 2174 | if (sci->sc_stage.scnt == NILFS_ST_DONE && | 2155 | if (sci->sc_stage.scnt == NILFS_ST_DONE && |
| 2175 | NILFS_SEG_EMPTY(&sci->sc_curseg->sb_sum)) { | 2156 | NILFS_SEG_EMPTY(&sci->sc_curseg->sb_sum)) { |
| 2176 | nilfs_segctor_end_construction(sci, nilfs, 1); | 2157 | nilfs_segctor_abort_construction(sci, nilfs, 1); |
| 2177 | goto out; | 2158 | goto out; |
| 2178 | } | 2159 | } |
| 2179 | 2160 | ||
| @@ -2187,7 +2168,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) | |||
| 2187 | if (has_sr) { | 2168 | if (has_sr) { |
| 2188 | err = nilfs_segctor_fill_in_checkpoint(sci); | 2169 | err = nilfs_segctor_fill_in_checkpoint(sci); |
| 2189 | if (unlikely(err)) | 2170 | if (unlikely(err)) |
| 2190 | goto failed_to_make_up; | 2171 | goto failed_to_write; |
| 2191 | 2172 | ||
| 2192 | nilfs_segctor_fill_in_super_root(sci, nilfs); | 2173 | nilfs_segctor_fill_in_super_root(sci, nilfs); |
| 2193 | } | 2174 | } |
| @@ -2195,42 +2176,46 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) | |||
| 2195 | 2176 | ||
| 2196 | /* Write partial segments */ | 2177 | /* Write partial segments */ |
| 2197 | err = nilfs_segctor_prepare_write(sci, &failed_page); | 2178 | err = nilfs_segctor_prepare_write(sci, &failed_page); |
| 2198 | if (unlikely(err)) | 2179 | if (err) { |
| 2180 | nilfs_abort_logs(&sci->sc_segbufs, failed_page, | ||
| 2181 | sci->sc_super_root, err); | ||
| 2199 | goto failed_to_write; | 2182 | goto failed_to_write; |
| 2200 | 2183 | } | |
| 2201 | nilfs_segctor_fill_in_checksums(sci, nilfs->ns_crc_seed); | 2184 | nilfs_segctor_fill_in_checksums(sci, nilfs->ns_crc_seed); |
| 2202 | 2185 | ||
| 2203 | err = nilfs_segctor_write(sci, nilfs->ns_bdi); | 2186 | err = nilfs_segctor_write(sci, nilfs); |
| 2204 | if (unlikely(err)) | 2187 | if (unlikely(err)) |
| 2205 | goto failed_to_write; | 2188 | goto failed_to_write; |
| 2206 | 2189 | ||
| 2207 | nilfs_segctor_complete_write(sci); | 2190 | if (sci->sc_stage.scnt == NILFS_ST_DONE || |
| 2208 | 2191 | nilfs->ns_blocksize_bits != PAGE_CACHE_SHIFT) { | |
| 2209 | /* Commit segments */ | 2192 | /* |
| 2210 | if (has_sr) | 2193 | * At this point, we avoid double buffering |
| 2211 | nilfs_segctor_clear_metadata_dirty(sci); | 2194 | * for blocksize < pagesize because page dirty |
| 2212 | 2195 | * flag is turned off during write and dirty | |
| 2213 | nilfs_segctor_end_construction(sci, nilfs, 0); | 2196 | * buffers are not properly collected for |
| 2214 | 2197 | * pages crossing over segments. | |
| 2198 | */ | ||
| 2199 | err = nilfs_segctor_wait(sci); | ||
| 2200 | if (err) | ||
| 2201 | goto failed_to_write; | ||
| 2202 | } | ||
| 2215 | } while (sci->sc_stage.scnt != NILFS_ST_DONE); | 2203 | } while (sci->sc_stage.scnt != NILFS_ST_DONE); |
| 2216 | 2204 | ||
| 2205 | sci->sc_super_root = NULL; | ||
| 2206 | |||
| 2217 | out: | 2207 | out: |
| 2218 | nilfs_segctor_destroy_segment_buffers(sci); | ||
| 2219 | nilfs_segctor_check_out_files(sci, sbi); | 2208 | nilfs_segctor_check_out_files(sci, sbi); |
| 2220 | return err; | 2209 | return err; |
| 2221 | 2210 | ||
| 2222 | failed_to_write: | 2211 | failed_to_write: |
| 2223 | nilfs_segctor_abort_write(sci, failed_page, err); | ||
| 2224 | nilfs_segctor_cancel_segusage(sci, nilfs->ns_sufile); | ||
| 2225 | |||
| 2226 | failed_to_make_up: | ||
| 2227 | if (sci->sc_stage.flags & NILFS_CF_IFILE_STARTED) | 2212 | if (sci->sc_stage.flags & NILFS_CF_IFILE_STARTED) |
| 2228 | nilfs_redirty_inodes(&sci->sc_dirty_files); | 2213 | nilfs_redirty_inodes(&sci->sc_dirty_files); |
| 2229 | 2214 | ||
| 2230 | failed: | 2215 | failed: |
| 2231 | if (nilfs_doing_gc()) | 2216 | if (nilfs_doing_gc()) |
| 2232 | nilfs_redirty_inodes(&sci->sc_gc_inodes); | 2217 | nilfs_redirty_inodes(&sci->sc_gc_inodes); |
| 2233 | nilfs_segctor_end_construction(sci, nilfs, err); | 2218 | nilfs_segctor_abort_construction(sci, nilfs, err); |
| 2234 | goto out; | 2219 | goto out; |
| 2235 | } | 2220 | } |
| 2236 | 2221 | ||
| @@ -2559,7 +2544,7 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, | |||
| 2559 | 2544 | ||
| 2560 | sci->sc_freesegs = kbufs[4]; | 2545 | sci->sc_freesegs = kbufs[4]; |
| 2561 | sci->sc_nfreesegs = argv[4].v_nmembs; | 2546 | sci->sc_nfreesegs = argv[4].v_nmembs; |
| 2562 | list_splice_init(&nilfs->ns_gc_inodes, sci->sc_gc_inodes.prev); | 2547 | list_splice_tail_init(&nilfs->ns_gc_inodes, &sci->sc_gc_inodes); |
| 2563 | 2548 | ||
| 2564 | for (;;) { | 2549 | for (;;) { |
| 2565 | nilfs_segctor_accept(sci, &req); | 2550 | nilfs_segctor_accept(sci, &req); |
| @@ -2788,6 +2773,7 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi) | |||
| 2788 | spin_lock_init(&sci->sc_state_lock); | 2773 | spin_lock_init(&sci->sc_state_lock); |
| 2789 | INIT_LIST_HEAD(&sci->sc_dirty_files); | 2774 | INIT_LIST_HEAD(&sci->sc_dirty_files); |
| 2790 | INIT_LIST_HEAD(&sci->sc_segbufs); | 2775 | INIT_LIST_HEAD(&sci->sc_segbufs); |
| 2776 | INIT_LIST_HEAD(&sci->sc_write_logs); | ||
| 2791 | INIT_LIST_HEAD(&sci->sc_gc_inodes); | 2777 | INIT_LIST_HEAD(&sci->sc_gc_inodes); |
| 2792 | INIT_LIST_HEAD(&sci->sc_copied_buffers); | 2778 | INIT_LIST_HEAD(&sci->sc_copied_buffers); |
| 2793 | 2779 | ||
| @@ -2855,6 +2841,7 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) | |||
| 2855 | } | 2841 | } |
| 2856 | 2842 | ||
| 2857 | WARN_ON(!list_empty(&sci->sc_segbufs)); | 2843 | WARN_ON(!list_empty(&sci->sc_segbufs)); |
| 2844 | WARN_ON(!list_empty(&sci->sc_write_logs)); | ||
| 2858 | 2845 | ||
| 2859 | down_write(&sbi->s_nilfs->ns_segctor_sem); | 2846 | down_write(&sbi->s_nilfs->ns_segctor_sem); |
| 2860 | 2847 | ||
