On 31.10.2010 17:08, Daniel Shahaf wrote:
> stefan2_at_apache.org wrote on Sun, Oct 31, 2010 at 15:22:31 -0000:
>> Author: stefan2
>> Date: Sun Oct 31 15:22:31 2010
>> New Revision: 1029381
>> URL: http://svn.apache.org/viewvc?rev=1029381&view=rev
>> Fix another packing issue. Due to concurrent access alone
>> it may happen that between determining the rev file name
>> and actually opening it, that very revision may get packed
>> (actually, get deleted after packing).
>> The file handle cache adds another issue: an open file handle
>> may not be suitable due to different open flags and the file
>> must be re-opened. While the existing handle would have
>> kept the file content alive, opening a new handle to the same
>> file will fail if the file was deleted before.
>> Since there can be only one transition from non-packed to
>> packed, we need to retry only once if we could not find the
>> revision file in question.
>> * subversion/libsvn_fs_fs/fs_fs.c
>> (open_pack_or_rev_file): retry once because the file might have
>> gotten packed.
>> Modified: subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c
>> URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c?rev=1029381&r1=1029380&r2=1029381&view=diff
>> --- subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c (original)
>> +++ subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c Sun Oct 31 15:22:31 2010
>> @@ -1939,34 +1939,54 @@ open_pack_or_rev_file(svn_file_handle_ca
> (the unidiff is unreadable, so I'll just paste the whole function)
>> static svn_error_t *
>> open_pack_or_rev_file(svn_file_handle_cache__handle_t **file,
>> svn_fs_t *fs,
>> svn_revnum_t rev,
>> apr_off_t offset,
>> int cookie,
>> apr_pool_t *pool)
>> svn_error_t *err;
>> const char *path;
>> svn_boolean_t retry = FALSE;
>> fs_fs_data_t *ffd = fs->fsap_data;
>> /* make sure file has a defined state */
>> *file = NULL;
>> err = svn_fs_fs__path_rev_absolute(&path, fs, rev, pool);
> So, now this call is inside the retry loop. But it does its own retry
> loop already. Looking at svn_fs_fs__path_rev_absolute()'s other
> callers, they all run under the fsfs write lock (which pack operations
> also acquire) except for the one in lock.c. So, I suppose we can remove
> the retry logic from svn_fs_fs__path_rev_absolute() and add it in lock.c
> (where it's currently absent).
The retry logic in svn_fs_fs__path_rev_absolute() seems
to be gone by now. With r1037470 and assuming proper
locking of FSFS repositories during requests, the retry
loop in open_pack_or_rev_file() will only be needed if the
repo gets packed within the same repository session.
> Also, svn_fs_fs__path_rev_absolute()'s docstring could warn that its
> result is "unstable" (points to a path that may vanish under certain
Done in r1037586.
>> if (! err)
>> /* open the revision file in buffered r/o mode */
>> err = svn_file_handle_cache__open(file,
>> APR_READ | APR_BUFFERED,
>> /* if that succeeded, there must be an underlying APR file */
>> assert(err || svn_file_handle_cache__get_apr_handle(*file));
>> if (err&& APR_STATUS_IS_ENOENT(err->apr_err))
>> /* Could not open the file. This may happen if the
>> * file once existed but got packed later. Note that
>> * the file handle cache may have had an open handle
>> * to the old file but had to close it in the function
>> * call above due to different open flags.
>> /* if that was our 2nd attempt, leave it at that. */
>> if (retry)
>> return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
>> _("No such revision %ld"), rev);
>> /* we failed for the first time. Refresh caches& retry. */
>> SVN_ERR(update_min_unpacked_rev(fs, pool));
>> retry = TRUE;
> Need "else\n return svn_error_return(err);" here, to prevent leaking the
> error when retry=TRUE.
Done in r1037552. The real issue is not the error
leak but the potential infinite loop if there is some
unexpected error after the first iteration.
>> while (err&& retry);
>> return svn_error_return(err);
Received on 2010-11-22 02:40:11 CET