Author: ivan Date: Tue Sep 3 09:52:47 2013 New Revision: 1519624 URL: http://svn.apache.org/r1519624 Log: Fix potential FSFS transaction corruption issue. The issue could happen only if processes are writing to the same transaction and using extremely large path.
* subversion/libsvn_fs_fs/low_level.c (write_change_entry): Collect all change info in stringbuf and write in one atomic write call. * subversion/libsvn_fs_fs/transaction.c (svn_fs_fs__add_change): Remove APR_BUFFERED flag when opening changes file for appending. Modified: subversion/trunk/subversion/libsvn_fs_fs/low_level.c subversion/trunk/subversion/libsvn_fs_fs/transaction.c Modified: subversion/trunk/subversion/libsvn_fs_fs/low_level.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/low_level.c?rev=1519624&r1=1519623&r2=1519624&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_fs_fs/low_level.c (original) +++ subversion/trunk/subversion/libsvn_fs_fs/low_level.c Tue Sep 3 09:52:47 2013 @@ -350,9 +350,11 @@ write_change_entry(svn_stream_t *stream, svn_boolean_t include_node_kind, apr_pool_t *pool) { - const char *idstr, *buf; + const char *idstr; const char *change_string = NULL; const char *kind_string = ""; + svn_stringbuf_t *buf; + apr_size_t len; switch (change->change_kind) { @@ -391,22 +393,24 @@ write_change_entry(svn_stream_t *stream, ? SVN_FS_FS__KIND_DIR : SVN_FS_FS__KIND_FILE); } - buf = apr_psprintf(pool, "%s %s%s %s %s %s\n", - idstr, change_string, kind_string, - change->text_mod ? FLAG_TRUE : FLAG_FALSE, - change->prop_mod ? FLAG_TRUE : FLAG_FALSE, - path); - - SVN_ERR(svn_stream_puts(stream, buf)); + buf = svn_stringbuf_createf(pool, "%s %s%s %s %s %s\n", + idstr, change_string, kind_string, + change->text_mod ? FLAG_TRUE : FLAG_FALSE, + change->prop_mod ? FLAG_TRUE : FLAG_FALSE, + path); if (SVN_IS_VALID_REVNUM(change->copyfrom_rev)) { - buf = apr_psprintf(pool, "%ld %s", change->copyfrom_rev, - change->copyfrom_path); - SVN_ERR(svn_stream_puts(stream, buf)); + svn_stringbuf_appendcstr(buf, apr_psprintf(pool, "%ld %s", + change->copyfrom_rev, + change->copyfrom_path)); } - return svn_error_trace(svn_stream_puts(stream, "\n")); + svn_stringbuf_appendbyte(buf, '\n'); + + /* Write all change info in one write call. */ + len = buf->len; + return svn_error_trace(svn_stream_write(stream, buf->data, &len)); } svn_error_t * Modified: subversion/trunk/subversion/libsvn_fs_fs/transaction.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/transaction.c?rev=1519624&r1=1519623&r2=1519624&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_fs_fs/transaction.c (original) +++ subversion/trunk/subversion/libsvn_fs_fs/transaction.c Tue Sep 3 09:52:47 2013 @@ -1518,9 +1518,10 @@ svn_fs_fs__add_change(svn_fs_t *fs, svn_fs_path_change2_t *change; apr_hash_t *changes = apr_hash_make(pool); + /* Not using APR_BUFFERED to append change in one atomic write operation. */ SVN_ERR(svn_io_file_open(&file, path_txn_changes(fs, txn_id, pool), - APR_APPEND | APR_WRITE | APR_CREATE - | APR_BUFFERED, APR_OS_DEFAULT, pool)); + APR_APPEND | APR_WRITE | APR_CREATE, + APR_OS_DEFAULT, pool)); change = svn_fs__path_change_create_internal(id, change_kind, pool); change->text_mod = text_mod;