aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;