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 | ||