Author: ivan
Date: Wed Jun 3 15:48:35 2015
New Revision: 1683378
URL: http://svn.apache.org/r1683378
Log:
Prevent a possible FSFS repository corruption with power or network disk
failures during 'svnadmin pack'.
* subversion/libsvn_fs_fs/pack.c
(close_pack_context): Call svn_io_file_flush_to_disk() for pack file.
(pack_phys_addressed): Use svn_io_file_open() to open pack and manifest
file and call svn_io_file_flush_to_disk() before closing them.
* subversion/libsvn_fs_fs/revprops.c
(svn_fs_fs__copy_revprops): Use apr_file_t to write pack file and flush
changes to disk before close.
(svn_fs_fs__pack_revprops_shard): Use svn_io_file_open() to packed revision
properties manifest file and call svn_io_file_flush_to_disk()
before closing it.
Modified:
subversion/trunk/subversion/libsvn_fs_fs/pack.c
subversion/trunk/subversion/libsvn_fs_fs/revprops.c
Modified: subversion/trunk/subversion/libsvn_fs_fs/pack.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/pack.c?rev=1683378&r1=1683377&r2=1683378&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/pack.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/pack.c Wed Jun 3 15:48:35 2015
@@ -384,6 +384,8 @@ close_pack_context(pack_context_t *conte
SVN_ERR(svn_io_remove_file2(proto_l2p_index_path, FALSE, pool));
SVN_ERR(svn_io_remove_file2(proto_p2l_index_path, FALSE, pool));
+ /* Ensure that packed file is written to disk.*/
+ SVN_ERR(svn_io_file_flush_to_disk(context->pack_file, pool));
SVN_ERR(svn_io_file_close(context->pack_file, pool));
return SVN_NO_ERROR;
@@ -1654,7 +1656,9 @@ pack_phys_addressed(const char *pack_fil
apr_pool_t *pool)
{
const char *pack_file_path, *manifest_file_path;
- svn_stream_t *pack_stream, *manifest_stream;
+ apr_file_t *pack_file;
+ apr_file_t *manifest_file;
+ svn_stream_t *manifest_stream;
svn_revnum_t end_rev, rev;
apr_off_t next_offset;
apr_pool_t *iterpool;
@@ -1663,13 +1667,18 @@ pack_phys_addressed(const char *pack_fil
pack_file_path = svn_dirent_join(pack_file_dir, PATH_PACKED, pool);
manifest_file_path = svn_dirent_join(pack_file_dir, PATH_MANIFEST, pool);
- /* Create the new directory and pack file. */
- SVN_ERR(svn_stream_open_writable(&pack_stream, pack_file_path, pool,
- pool));
+ /* Create the new directory and pack file.
+ * Use unbuffered apr_file_t since we're going to write using 16kb
+ * chunks. */
+ SVN_ERR(svn_io_file_open(&pack_file, pack_file_path,
+ APR_WRITE | APR_CREATE | APR_EXCL,
+ APR_OS_DEFAULT, pool));
/* Create the manifest file. */
- SVN_ERR(svn_stream_open_writable(&manifest_stream, manifest_file_path,
- pool, pool));
+ SVN_ERR(svn_io_file_open(&manifest_file, manifest_file_path,
+ APR_WRITE | APR_BUFFERED | APR_CREATE | APR_EXCL,
+ APR_OS_DEFAULT, pool));
+ manifest_stream = svn_stream_from_aprfile2(manifest_file, TRUE, pool);
end_rev = start_rev + max_files_per_dir - 1;
next_offset = 0;
@@ -1696,16 +1705,24 @@ pack_phys_addressed(const char *pack_fil
/* Copy all the bits from the rev file to the end of the pack file. */
SVN_ERR(svn_stream_open_readonly(&rev_stream, path, iterpool, iterpool));
- SVN_ERR(svn_stream_copy3(rev_stream, svn_stream_disown(pack_stream,
- iterpool),
+ SVN_ERR(svn_stream_copy3(rev_stream,
+ svn_stream_from_aprfile2(pack_file, TRUE, pool),
cancel_func, cancel_baton, iterpool));
}
- /* disallow write access to the manifest file */
+ /* Close stream over APR file. */
SVN_ERR(svn_stream_close(manifest_stream));
+
+ /* Ensure that pack file is written to disk. */
+ SVN_ERR(svn_io_file_flush_to_disk(manifest_file, pool));
+ SVN_ERR(svn_io_file_close(manifest_file, pool));
+
+ /* disallow write access to the manifest file */
SVN_ERR(svn_io_set_file_read_only(manifest_file_path, FALSE, iterpool));
- SVN_ERR(svn_stream_close(pack_stream));
+ /* Ensure that pack file is written to disk. */
+ SVN_ERR(svn_io_file_flush_to_disk(pack_file, pool));
+ SVN_ERR(svn_io_file_close(pack_file, pool));
svn_pool_destroy(iterpool);
Modified: subversion/trunk/subversion/libsvn_fs_fs/revprops.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/revprops.c?rev=1683378&r1=1683377&r2=1683378&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/revprops.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/revprops.c Wed Jun 3 15:48:35 2015
@@ -1168,7 +1168,6 @@ svn_fs_fs__copy_revprops(const char *pac
apr_file_t *pack_file;
svn_revnum_t rev;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
- svn_stream_t *stream;
/* create empty data buffer and a write stream on top of it */
svn_stringbuf_t *uncompressed
@@ -1192,6 +1191,7 @@ svn_fs_fs__copy_revprops(const char *pac
for (rev = start_rev; rev <= end_rev; rev++)
{
const char *path;
+ svn_stream_t *stream;
svn_pool_clear(iterpool);
@@ -1213,9 +1213,10 @@ svn_fs_fs__copy_revprops(const char *pac
SVN_ERR(svn__compress(uncompressed, compressed, compression_level));
/* write the pack file content to disk */
- stream = svn_stream_from_aprfile2(pack_file, FALSE, scratch_pool);
- SVN_ERR(svn_stream_write(stream, compressed->data, &compressed->len));
- SVN_ERR(svn_stream_close(stream));
+ SVN_ERR(svn_io_file_write_full(pack_file, compressed->data, compressed->len,
+ NULL, scratch_pool));
+ SVN_ERR(svn_io_file_flush_to_disk(pack_file, scratch_pool));
+ SVN_ERR(svn_io_file_close(pack_file, scratch_pool));
svn_pool_destroy(iterpool);
@@ -1234,6 +1235,7 @@ svn_fs_fs__pack_revprops_shard(const cha
apr_pool_t *scratch_pool)
{
const char *manifest_file_path, *pack_filename = NULL;
+ apr_file_t *manifest_file;
svn_stream_t *manifest_stream;
svn_revnum_t start_rev, end_rev, rev;
apr_off_t total_size;
@@ -1250,8 +1252,12 @@ svn_fs_fs__pack_revprops_shard(const cha
/* Create the new directory and manifest file stream. */
SVN_ERR(svn_io_dir_make(pack_file_dir, APR_OS_DEFAULT, scratch_pool));
- SVN_ERR(svn_stream_open_writable(&manifest_stream, manifest_file_path,
- scratch_pool, scratch_pool));
+
+ SVN_ERR(svn_io_file_open(&manifest_file, manifest_file_path,
+ APR_WRITE | APR_BUFFERED | APR_CREATE | APR_EXCL,
+ APR_OS_DEFAULT, scratch_pool));
+ manifest_stream = svn_stream_from_aprfile2(manifest_file, TRUE,
+ scratch_pool);
/* revisions to handle. Special case: revision 0 */
start_rev = (svn_revnum_t) (shard * max_files_per_dir);
@@ -1318,8 +1324,10 @@ svn_fs_fs__pack_revprops_shard(const cha
compression_level, cancel_func,
cancel_baton, iterpool));
- /* flush the manifest file and update permissions */
+ /* flush the manifest file to disk and update permissions */
SVN_ERR(svn_stream_close(manifest_stream));
+ SVN_ERR(svn_io_file_flush_to_disk(manifest_file, iterpool));
+ SVN_ERR(svn_io_file_close(manifest_file, iterpool));
SVN_ERR(svn_io_copy_perms(shard_path, pack_file_dir, iterpool));
svn_pool_destroy(iterpool);