aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2009-11-29 09:03:04 -0500
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2009-11-30 07:17:52 -0500
commita694291a6211537189c6080f77f63cdabfc9b63e (patch)
treeec23d36fc493eeaaedd72f54187652f9df3b4819 /fs/nilfs2
parente29df395bc6d2d0c89b3d8a5939a24b1b43c2fb6 (diff)
nilfs2: separate wait function from nilfs_segctor_write
This separates wait function for submitted logs from the write function nilfs_segctor_write(). A new list of segment buffers "sc_write_logs" is added to hold logs under writing, and double buffering is partially applied to hide io latency. At this point, the double buffering is disabled for blocksize < pagesize because page dirty flag is turned off during write and dirty buffers are not properly collected for pages crossing over segments. To receive full benefit of the double buffering, further refinement is needed to move the io wait outside the lock section of log writer. Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs/nilfs2')
-rw-r--r--fs/nilfs2/segbuf.c16
-rw-r--r--fs/nilfs2/segbuf.h2
-rw-r--r--fs/nilfs2/segment.c240
-rw-r--r--fs/nilfs2/segment.h2
4 files changed, 165 insertions, 95 deletions
diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c
index d856d62bf886..645c78656aa0 100644
--- a/fs/nilfs2/segbuf.c
+++ b/fs/nilfs2/segbuf.c
@@ -100,6 +100,22 @@ void nilfs_segbuf_map(struct nilfs_segment_buffer *segbuf, __u64 segnum,
100 segbuf->sb_fseg_end - segbuf->sb_pseg_start + 1; 100 segbuf->sb_fseg_end - segbuf->sb_pseg_start + 1;
101} 101}
102 102
103/**
104 * nilfs_segbuf_map_cont - map a new log behind a given log
105 * @segbuf: new segment buffer
106 * @prev: segment buffer containing a log to be continued
107 */
108void nilfs_segbuf_map_cont(struct nilfs_segment_buffer *segbuf,
109 struct nilfs_segment_buffer *prev)
110{
111 segbuf->sb_segnum = prev->sb_segnum;
112 segbuf->sb_fseg_start = prev->sb_fseg_start;
113 segbuf->sb_fseg_end = prev->sb_fseg_end;
114 segbuf->sb_pseg_start = prev->sb_pseg_start + prev->sb_sum.nblocks;
115 segbuf->sb_rest_blocks =
116 segbuf->sb_fseg_end - segbuf->sb_pseg_start + 1;
117}
118
103void nilfs_segbuf_set_next_segnum(struct nilfs_segment_buffer *segbuf, 119void nilfs_segbuf_set_next_segnum(struct nilfs_segment_buffer *segbuf,
104 __u64 nextnum, struct the_nilfs *nilfs) 120 __u64 nextnum, struct the_nilfs *nilfs)
105{ 121{
diff --git a/fs/nilfs2/segbuf.h b/fs/nilfs2/segbuf.h
index 7fbaf5eee016..6af1630fb401 100644
--- a/fs/nilfs2/segbuf.h
+++ b/fs/nilfs2/segbuf.h
@@ -128,6 +128,8 @@ struct nilfs_segment_buffer *nilfs_segbuf_new(struct super_block *);
128void nilfs_segbuf_free(struct nilfs_segment_buffer *); 128void nilfs_segbuf_free(struct nilfs_segment_buffer *);
129void nilfs_segbuf_map(struct nilfs_segment_buffer *, __u64, unsigned long, 129void nilfs_segbuf_map(struct nilfs_segment_buffer *, __u64, unsigned long,
130 struct the_nilfs *); 130 struct the_nilfs *);
131void nilfs_segbuf_map_cont(struct nilfs_segment_buffer *segbuf,
132 struct nilfs_segment_buffer *prev);
131void nilfs_segbuf_set_next_segnum(struct nilfs_segment_buffer *, __u64, 133void nilfs_segbuf_set_next_segnum(struct nilfs_segment_buffer *, __u64,
132 struct the_nilfs *); 134 struct the_nilfs *);
133int nilfs_segbuf_reset(struct nilfs_segment_buffer *, unsigned, time_t); 135int nilfs_segbuf_reset(struct nilfs_segment_buffer *, unsigned, time_t);
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 689deb9d41d1..17584c524486 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -1273,48 +1273,69 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
1273 return err; 1273 return err;
1274} 1274}
1275 1275
1276/**
1277 * nilfs_segctor_begin_construction - setup segment buffer to make a new log
1278 * @sci: nilfs_sc_info
1279 * @nilfs: nilfs object
1280 */
1276static int nilfs_segctor_begin_construction(struct nilfs_sc_info *sci, 1281static int nilfs_segctor_begin_construction(struct nilfs_sc_info *sci,
1277 struct the_nilfs *nilfs) 1282 struct the_nilfs *nilfs)
1278{ 1283{
1279 struct nilfs_segment_buffer *segbuf; 1284 struct nilfs_segment_buffer *segbuf, *prev;
1280 __u64 nextnum; 1285 __u64 nextnum;
1281 int err; 1286 int err, alloc = 0;
1282 1287
1283 if (list_empty(&sci->sc_segbufs)) { 1288 segbuf = nilfs_segbuf_new(sci->sc_super);
1284 segbuf = nilfs_segbuf_new(sci->sc_super); 1289 if (unlikely(!segbuf))
1285 if (unlikely(!segbuf)) 1290 return -ENOMEM;
1286 return -ENOMEM;
1287 list_add(&segbuf->sb_list, &sci->sc_segbufs);
1288 } else
1289 segbuf = NILFS_FIRST_SEGBUF(&sci->sc_segbufs);
1290 1291
1291 nilfs_segbuf_map(segbuf, nilfs->ns_segnum, nilfs->ns_pseg_offset, 1292 if (list_empty(&sci->sc_write_logs)) {
1292 nilfs); 1293 nilfs_segbuf_map(segbuf, nilfs->ns_segnum,
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 }
1293 1299
1294 if (segbuf->sb_rest_blocks < NILFS_PSEG_MIN_BLOCKS) { 1300 segbuf->sb_sum.seg_seq = nilfs->ns_seg_seq;
1295 nilfs_shift_to_next_segment(nilfs); 1301 nextnum = nilfs->ns_nextnum;
1296 nilfs_segbuf_map(segbuf, nilfs->ns_segnum, 0, nilfs); 1302
1303 if (nilfs->ns_segnum == nilfs->ns_nextnum)
1304 /* Start from the head of a new full segment */
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 }
1297 } 1318 }
1298 sci->sc_segbuf_nblocks = segbuf->sb_rest_blocks;
1299 1319
1300 err = nilfs_sufile_mark_dirty(nilfs->ns_sufile, segbuf->sb_segnum); 1320 err = nilfs_sufile_mark_dirty(nilfs->ns_sufile, segbuf->sb_segnum);
1301 if (unlikely(err)) 1321 if (err)
1302 return err; 1322 goto failed;
1303 1323
1304 if (nilfs->ns_segnum == nilfs->ns_nextnum) { 1324 if (alloc) {
1305 /* Start from the head of a new full segment */
1306 err = nilfs_sufile_alloc(nilfs->ns_sufile, &nextnum); 1325 err = nilfs_sufile_alloc(nilfs->ns_sufile, &nextnum);
1307 if (unlikely(err)) 1326 if (err)
1308 return err; 1327 goto failed;
1309 } else 1328 }
1310 nextnum = nilfs->ns_nextnum;
1311
1312 segbuf->sb_sum.seg_seq = nilfs->ns_seg_seq;
1313 nilfs_segbuf_set_next_segnum(segbuf, nextnum, nilfs); 1329 nilfs_segbuf_set_next_segnum(segbuf, nextnum, nilfs);
1314 1330
1315 /* truncating segment buffers */ 1331 BUG_ON(!list_empty(&sci->sc_segbufs));
1316 nilfs_truncate_logs(&sci->sc_segbufs, segbuf); 1332 list_add_tail(&segbuf->sb_list, &sci->sc_segbufs);
1333 sci->sc_segbuf_nblocks = segbuf->sb_rest_blocks;
1317 return 0; 1334 return 0;
1335
1336 failed:
1337 nilfs_segbuf_free(segbuf);
1338 return err;
1318} 1339}
1319 1340
1320static int nilfs_segctor_extend_segments(struct nilfs_sc_info *sci, 1341static int nilfs_segctor_extend_segments(struct nilfs_sc_info *sci,
@@ -1373,15 +1394,16 @@ static int nilfs_segctor_extend_segments(struct nilfs_sc_info *sci,
1373 return err; 1394 return err;
1374} 1395}
1375 1396
1376static void nilfs_segctor_free_incomplete_segments(struct nilfs_sc_info *sci, 1397static void nilfs_free_incomplete_logs(struct list_head *logs,
1377 struct the_nilfs *nilfs) 1398 struct the_nilfs *nilfs)
1378{ 1399{
1379 struct nilfs_segment_buffer *segbuf; 1400 struct nilfs_segment_buffer *segbuf, *prev;
1401 struct inode *sufile = nilfs->ns_sufile;
1380 int ret; 1402 int ret;
1381 1403
1382 segbuf = NILFS_FIRST_SEGBUF(&sci->sc_segbufs); 1404 segbuf = NILFS_FIRST_SEGBUF(logs);
1383 if (nilfs->ns_nextnum != segbuf->sb_nextnum) { 1405 if (nilfs->ns_nextnum != segbuf->sb_nextnum) {
1384 ret = nilfs_sufile_free(nilfs->ns_sufile, segbuf->sb_nextnum); 1406 ret = nilfs_sufile_free(sufile, segbuf->sb_nextnum);
1385 WARN_ON(ret); /* never fails */ 1407 WARN_ON(ret); /* never fails */
1386 } 1408 }
1387 if (atomic_read(&segbuf->sb_err)) { 1409 if (atomic_read(&segbuf->sb_err)) {
@@ -1395,34 +1417,18 @@ static void nilfs_segctor_free_incomplete_segments(struct nilfs_sc_info *sci,
1395 set_nilfs_discontinued(nilfs); 1417 set_nilfs_discontinued(nilfs);
1396 } 1418 }
1397 1419
1398 list_for_each_entry_continue(segbuf, &sci->sc_segbufs, sb_list) { 1420 prev = segbuf;
1399 ret = nilfs_sufile_free(nilfs->ns_sufile, segbuf->sb_nextnum); 1421 list_for_each_entry_continue(segbuf, logs, sb_list) {
1400 WARN_ON(ret); /* never fails */ 1422 if (prev->sb_nextnum != segbuf->sb_nextnum) {
1423 ret = nilfs_sufile_free(sufile, segbuf->sb_nextnum);
1424 WARN_ON(ret); /* never fails */
1425 }
1401 if (atomic_read(&segbuf->sb_err) && 1426 if (atomic_read(&segbuf->sb_err) &&
1402 segbuf->sb_segnum != nilfs->ns_nextnum) 1427 segbuf->sb_segnum != nilfs->ns_nextnum)
1403 /* Case 2: extended segment (!= next) failed */ 1428 /* Case 2: extended segment (!= next) failed */
1404 nilfs_sufile_set_error(nilfs->ns_sufile, 1429 nilfs_sufile_set_error(sufile, segbuf->sb_segnum);
1405 segbuf->sb_segnum); 1430 prev = segbuf;
1406 }
1407}
1408
1409static void nilfs_segctor_end_construction(struct nilfs_sc_info *sci,
1410 struct the_nilfs *nilfs, int err)
1411{
1412 if (unlikely(err)) {
1413 nilfs_segctor_free_incomplete_segments(sci, nilfs);
1414 if (sci->sc_stage.flags & NILFS_CF_SUFREED) {
1415 int ret;
1416
1417 ret = nilfs_sufile_cancel_freev(nilfs->ns_sufile,
1418 sci->sc_freesegs,
1419 sci->sc_nfreesegs,
1420 NULL);
1421 WARN_ON(ret); /* do not happen */
1422 }
1423 } 1431 }
1424 nilfs_clear_logs(&sci->sc_segbufs);
1425 sci->sc_super_root = NULL;
1426} 1432}
1427 1433
1428static void nilfs_segctor_update_segusage(struct nilfs_sc_info *sci, 1434static void nilfs_segctor_update_segusage(struct nilfs_sc_info *sci,
@@ -1442,19 +1448,18 @@ static void nilfs_segctor_update_segusage(struct nilfs_sc_info *sci,
1442 } 1448 }
1443} 1449}
1444 1450
1445static void nilfs_segctor_cancel_segusage(struct nilfs_sc_info *sci, 1451static void nilfs_cancel_segusage(struct list_head *logs, struct inode *sufile)
1446 struct inode *sufile)
1447{ 1452{
1448 struct nilfs_segment_buffer *segbuf; 1453 struct nilfs_segment_buffer *segbuf;
1449 int ret; 1454 int ret;
1450 1455
1451 segbuf = NILFS_FIRST_SEGBUF(&sci->sc_segbufs); 1456 segbuf = NILFS_FIRST_SEGBUF(logs);
1452 ret = nilfs_sufile_set_segment_usage(sufile, segbuf->sb_segnum, 1457 ret = nilfs_sufile_set_segment_usage(sufile, segbuf->sb_segnum,
1453 segbuf->sb_pseg_start - 1458 segbuf->sb_pseg_start -
1454 segbuf->sb_fseg_start, 0); 1459 segbuf->sb_fseg_start, 0);
1455 WARN_ON(ret); /* always succeed because the segusage is dirty */ 1460 WARN_ON(ret); /* always succeed because the segusage is dirty */
1456 1461
1457 list_for_each_entry_continue(segbuf, &sci->sc_segbufs, sb_list) { 1462 list_for_each_entry_continue(segbuf, logs, sb_list) {
1458 ret = nilfs_sufile_set_segment_usage(sufile, segbuf->sb_segnum, 1463 ret = nilfs_sufile_set_segment_usage(sufile, segbuf->sb_segnum,
1459 0, 0); 1464 0, 0);
1460 WARN_ON(ret); /* always succeed */ 1465 WARN_ON(ret); /* always succeed */
@@ -1760,17 +1765,15 @@ static int nilfs_segctor_write(struct nilfs_sc_info *sci,
1760 struct the_nilfs *nilfs) 1765 struct the_nilfs *nilfs)
1761{ 1766{
1762 struct nilfs_segment_buffer *segbuf; 1767 struct nilfs_segment_buffer *segbuf;
1763 int err, res; 1768 int ret = 0;
1764 1769
1765 list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) { 1770 list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) {
1766 err = nilfs_segbuf_write(segbuf, nilfs); 1771 ret = nilfs_segbuf_write(segbuf, nilfs);
1767 1772 if (ret)
1768 res = nilfs_segbuf_wait(segbuf); 1773 break;
1769 err = err ? : res;
1770 if (err)
1771 return err;
1772 } 1774 }
1773 return 0; 1775 list_splice_tail_init(&sci->sc_segbufs, &sci->sc_write_logs);
1776 return ret;
1774} 1777}
1775 1778
1776static void __nilfs_end_page_io(struct page *page, int err) 1779static void __nilfs_end_page_io(struct page *page, int err)
@@ -1848,15 +1851,17 @@ static void nilfs_clear_copied_buffers(struct list_head *list, int err)
1848 } 1851 }
1849} 1852}
1850 1853
1851static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci, 1854static void nilfs_abort_logs(struct list_head *logs, struct page *failed_page,
1852 struct page *failed_page, int err) 1855 struct buffer_head *bh_sr, int err)
1853{ 1856{
1854 struct nilfs_segment_buffer *segbuf; 1857 struct nilfs_segment_buffer *segbuf;
1855 struct page *bd_page = NULL, *fs_page = NULL; 1858 struct page *bd_page = NULL, *fs_page = NULL;
1859 struct buffer_head *bh;
1856 1860
1857 list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) { 1861 if (list_empty(logs))
1858 struct buffer_head *bh; 1862 return;
1859 1863
1864 list_for_each_entry(segbuf, logs, sb_list) {
1860 list_for_each_entry(bh, &segbuf->sb_segsum_buffers, 1865 list_for_each_entry(bh, &segbuf->sb_segsum_buffers,
1861 b_assoc_buffers) { 1866 b_assoc_buffers) {
1862 if (bh->b_page != bd_page) { 1867 if (bh->b_page != bd_page) {
@@ -1868,7 +1873,7 @@ static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci,
1868 1873
1869 list_for_each_entry(bh, &segbuf->sb_payload_buffers, 1874 list_for_each_entry(bh, &segbuf->sb_payload_buffers,
1870 b_assoc_buffers) { 1875 b_assoc_buffers) {
1871 if (bh == sci->sc_super_root) { 1876 if (bh == bh_sr) {
1872 if (bh->b_page != bd_page) { 1877 if (bh->b_page != bd_page) {
1873 end_page_writeback(bd_page); 1878 end_page_writeback(bd_page);
1874 bd_page = bh->b_page; 1879 bd_page = bh->b_page;
@@ -1878,7 +1883,7 @@ static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci,
1878 if (bh->b_page != fs_page) { 1883 if (bh->b_page != fs_page) {
1879 nilfs_end_page_io(fs_page, err); 1884 nilfs_end_page_io(fs_page, err);
1880 if (fs_page && fs_page == failed_page) 1885 if (fs_page && fs_page == failed_page)
1881 goto done; 1886 return;
1882 fs_page = bh->b_page; 1887 fs_page = bh->b_page;
1883 } 1888 }
1884 } 1889 }
@@ -1887,8 +1892,34 @@ static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci,
1887 end_page_writeback(bd_page); 1892 end_page_writeback(bd_page);
1888 1893
1889 nilfs_end_page_io(fs_page, err); 1894 nilfs_end_page_io(fs_page, err);
1890 done: 1895}
1896
1897static 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);
1891 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;
1892} 1923}
1893 1924
1894static void nilfs_set_next_segment(struct the_nilfs *nilfs, 1925static void nilfs_set_next_segment(struct the_nilfs *nilfs,
@@ -1910,7 +1941,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)
1910 struct the_nilfs *nilfs = sbi->s_nilfs; 1941 struct the_nilfs *nilfs = sbi->s_nilfs;
1911 int update_sr = (sci->sc_super_root != NULL); 1942 int update_sr = (sci->sc_super_root != NULL);
1912 1943
1913 list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) { 1944 list_for_each_entry(segbuf, &sci->sc_write_logs, sb_list) {
1914 struct buffer_head *bh; 1945 struct buffer_head *bh;
1915 1946
1916 list_for_each_entry(bh, &segbuf->sb_segsum_buffers, 1947 list_for_each_entry(bh, &segbuf->sb_segsum_buffers,
@@ -1983,7 +2014,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)
1983 2014
1984 sci->sc_nblk_inc += sci->sc_nblk_this_inc; 2015 sci->sc_nblk_inc += sci->sc_nblk_this_inc;
1985 2016
1986 segbuf = NILFS_LAST_SEGBUF(&sci->sc_segbufs); 2017 segbuf = NILFS_LAST_SEGBUF(&sci->sc_write_logs);
1987 nilfs_set_next_segment(nilfs, segbuf); 2018 nilfs_set_next_segment(nilfs, segbuf);
1988 2019
1989 if (update_sr) { 2020 if (update_sr) {
@@ -1994,10 +2025,23 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)
1994 clear_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags); 2025 clear_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags);
1995 clear_bit(NILFS_SC_DIRTY, &sci->sc_flags); 2026 clear_bit(NILFS_SC_DIRTY, &sci->sc_flags);
1996 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);
1997 } else 2029 } else
1998 clear_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags); 2030 clear_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags);
1999} 2031}
2000 2032
2033static 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
2001static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, 2045static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci,
2002 struct nilfs_sb_info *sbi) 2046 struct nilfs_sb_info *sbi)
2003{ 2047{
@@ -2110,7 +2154,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
2110 /* Avoid empty segment */ 2154 /* Avoid empty segment */
2111 if (sci->sc_stage.scnt == NILFS_ST_DONE && 2155 if (sci->sc_stage.scnt == NILFS_ST_DONE &&
2112 NILFS_SEG_EMPTY(&sci->sc_curseg->sb_sum)) { 2156 NILFS_SEG_EMPTY(&sci->sc_curseg->sb_sum)) {
2113 nilfs_segctor_end_construction(sci, nilfs, 1); 2157 nilfs_segctor_abort_construction(sci, nilfs, 1);
2114 goto out; 2158 goto out;
2115 } 2159 }
2116 2160
@@ -2124,7 +2168,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
2124 if (has_sr) { 2168 if (has_sr) {
2125 err = nilfs_segctor_fill_in_checkpoint(sci); 2169 err = nilfs_segctor_fill_in_checkpoint(sci);
2126 if (unlikely(err)) 2170 if (unlikely(err))
2127 goto failed_to_make_up; 2171 goto failed_to_write;
2128 2172
2129 nilfs_segctor_fill_in_super_root(sci, nilfs); 2173 nilfs_segctor_fill_in_super_root(sci, nilfs);
2130 } 2174 }
@@ -2132,42 +2176,46 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
2132 2176
2133 /* Write partial segments */ 2177 /* Write partial segments */
2134 err = nilfs_segctor_prepare_write(sci, &failed_page); 2178 err = nilfs_segctor_prepare_write(sci, &failed_page);
2135 if (unlikely(err)) 2179 if (err) {
2180 nilfs_abort_logs(&sci->sc_segbufs, failed_page,
2181 sci->sc_super_root, err);
2136 goto failed_to_write; 2182 goto failed_to_write;
2137 2183 }
2138 nilfs_segctor_fill_in_checksums(sci, nilfs->ns_crc_seed); 2184 nilfs_segctor_fill_in_checksums(sci, nilfs->ns_crc_seed);
2139 2185
2140 err = nilfs_segctor_write(sci, nilfs); 2186 err = nilfs_segctor_write(sci, nilfs);
2141 if (unlikely(err)) 2187 if (unlikely(err))
2142 goto failed_to_write; 2188 goto failed_to_write;
2143 2189
2144 nilfs_segctor_complete_write(sci); 2190 if (sci->sc_stage.scnt == NILFS_ST_DONE ||
2145 2191 nilfs->ns_blocksize_bits != PAGE_CACHE_SHIFT) {
2146 /* Commit segments */ 2192 /*
2147 if (has_sr) 2193 * At this point, we avoid double buffering
2148 nilfs_segctor_clear_metadata_dirty(sci); 2194 * for blocksize < pagesize because page dirty
2149 2195 * flag is turned off during write and dirty
2150 nilfs_segctor_end_construction(sci, nilfs, 0); 2196 * buffers are not properly collected for
2151 2197 * pages crossing over segments.
2198 */
2199 err = nilfs_segctor_wait(sci);
2200 if (err)
2201 goto failed_to_write;
2202 }
2152 } while (sci->sc_stage.scnt != NILFS_ST_DONE); 2203 } while (sci->sc_stage.scnt != NILFS_ST_DONE);
2153 2204
2205 sci->sc_super_root = NULL;
2206
2154 out: 2207 out:
2155 nilfs_destroy_logs(&sci->sc_segbufs);
2156 nilfs_segctor_check_out_files(sci, sbi); 2208 nilfs_segctor_check_out_files(sci, sbi);
2157 return err; 2209 return err;
2158 2210
2159 failed_to_write: 2211 failed_to_write:
2160 nilfs_segctor_abort_write(sci, failed_page, err);
2161 nilfs_segctor_cancel_segusage(sci, nilfs->ns_sufile);
2162
2163 failed_to_make_up:
2164 if (sci->sc_stage.flags & NILFS_CF_IFILE_STARTED) 2212 if (sci->sc_stage.flags & NILFS_CF_IFILE_STARTED)
2165 nilfs_redirty_inodes(&sci->sc_dirty_files); 2213 nilfs_redirty_inodes(&sci->sc_dirty_files);
2166 2214
2167 failed: 2215 failed:
2168 if (nilfs_doing_gc()) 2216 if (nilfs_doing_gc())
2169 nilfs_redirty_inodes(&sci->sc_gc_inodes); 2217 nilfs_redirty_inodes(&sci->sc_gc_inodes);
2170 nilfs_segctor_end_construction(sci, nilfs, err); 2218 nilfs_segctor_abort_construction(sci, nilfs, err);
2171 goto out; 2219 goto out;
2172} 2220}
2173 2221
@@ -2725,6 +2773,7 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi)
2725 spin_lock_init(&sci->sc_state_lock); 2773 spin_lock_init(&sci->sc_state_lock);
2726 INIT_LIST_HEAD(&sci->sc_dirty_files); 2774 INIT_LIST_HEAD(&sci->sc_dirty_files);
2727 INIT_LIST_HEAD(&sci->sc_segbufs); 2775 INIT_LIST_HEAD(&sci->sc_segbufs);
2776 INIT_LIST_HEAD(&sci->sc_write_logs);
2728 INIT_LIST_HEAD(&sci->sc_gc_inodes); 2777 INIT_LIST_HEAD(&sci->sc_gc_inodes);
2729 INIT_LIST_HEAD(&sci->sc_copied_buffers); 2778 INIT_LIST_HEAD(&sci->sc_copied_buffers);
2730 2779
@@ -2792,6 +2841,7 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
2792 } 2841 }
2793 2842
2794 WARN_ON(!list_empty(&sci->sc_segbufs)); 2843 WARN_ON(!list_empty(&sci->sc_segbufs));
2844 WARN_ON(!list_empty(&sci->sc_write_logs));
2795 2845
2796 down_write(&sbi->s_nilfs->ns_segctor_sem); 2846 down_write(&sbi->s_nilfs->ns_segctor_sem);
2797 2847
diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h
index 0d2a475a741b..3d3ab2f9864c 100644
--- a/fs/nilfs2/segment.h
+++ b/fs/nilfs2/segment.h
@@ -97,6 +97,7 @@ struct nilfs_segsum_pointer {
97 * @sc_dsync_start: start byte offset of data pages 97 * @sc_dsync_start: start byte offset of data pages
98 * @sc_dsync_end: end byte offset of data pages (inclusive) 98 * @sc_dsync_end: end byte offset of data pages (inclusive)
99 * @sc_segbufs: List of segment buffers 99 * @sc_segbufs: List of segment buffers
100 * @sc_write_logs: List of segment buffers to hold logs under writing
100 * @sc_segbuf_nblocks: Number of available blocks in segment buffers. 101 * @sc_segbuf_nblocks: Number of available blocks in segment buffers.
101 * @sc_curseg: Current segment buffer 102 * @sc_curseg: Current segment buffer
102 * @sc_super_root: Pointer to the super root buffer 103 * @sc_super_root: Pointer to the super root buffer
@@ -143,6 +144,7 @@ struct nilfs_sc_info {
143 144
144 /* Segment buffers */ 145 /* Segment buffers */
145 struct list_head sc_segbufs; 146 struct list_head sc_segbufs;
147 struct list_head sc_write_logs;
146 unsigned long sc_segbuf_nblocks; 148 unsigned long sc_segbuf_nblocks;
147 struct nilfs_segment_buffer *sc_curseg; 149 struct nilfs_segment_buffer *sc_curseg;
148 struct buffer_head *sc_super_root; 150 struct buffer_head *sc_super_root;