avoid concurrent access to hash offset
Since partial_hash::offset is not an atomic it is technically UD to access it concurrently from multiple threads.
This commit is contained in:
parent
241e9fd25a
commit
f36b9a805a
|
@ -2153,6 +2153,9 @@ namespace libtorrent
|
||||||
DLOG("kick_hasher: %d - %d (piece: %d offset: %d)\n"
|
DLOG("kick_hasher: %d - %d (piece: %d offset: %d)\n"
|
||||||
, cursor, end, int(pe->piece), ph->offset);
|
, cursor, end, int(pe->piece), ph->offset);
|
||||||
|
|
||||||
|
// save a local copy of offset to avoid concurrent access
|
||||||
|
int offset = ph->offset;
|
||||||
|
|
||||||
l.unlock();
|
l.unlock();
|
||||||
|
|
||||||
time_point start_time = clock_type::now();
|
time_point start_time = clock_type::now();
|
||||||
|
@ -2160,15 +2163,17 @@ namespace libtorrent
|
||||||
for (int i = cursor; i < end; ++i)
|
for (int i = cursor; i < end; ++i)
|
||||||
{
|
{
|
||||||
cached_block_entry& bl = pe->blocks[i];
|
cached_block_entry& bl = pe->blocks[i];
|
||||||
int size = (std::min)(block_size, piece_size - ph->offset);
|
int size = (std::min)(block_size, piece_size - offset);
|
||||||
ph->h.update(bl.buf, size);
|
ph->h.update(bl.buf, size);
|
||||||
ph->offset += size;
|
offset += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::uint64_t hash_time = total_microseconds(clock_type::now() - start_time);
|
boost::uint64_t hash_time = total_microseconds(clock_type::now() - start_time);
|
||||||
|
|
||||||
l.lock();
|
l.lock();
|
||||||
|
|
||||||
|
ph->offset = offset;
|
||||||
|
|
||||||
TORRENT_PIECE_ASSERT(pe->hashing, pe);
|
TORRENT_PIECE_ASSERT(pe->hashing, pe);
|
||||||
TORRENT_PIECE_ASSERT(pe->hash, pe);
|
TORRENT_PIECE_ASSERT(pe->hash, pe);
|
||||||
|
|
||||||
|
@ -2388,22 +2393,25 @@ namespace libtorrent
|
||||||
// to keep the cache footprint low, try to evict a volatile piece
|
// to keep the cache footprint low, try to evict a volatile piece
|
||||||
m_disk_cache.try_evict_one_volatile();
|
m_disk_cache.try_evict_one_volatile();
|
||||||
|
|
||||||
|
// save a local copy of offset to avoid concurrent access
|
||||||
|
int offset = ph->offset;
|
||||||
|
|
||||||
l.unlock();
|
l.unlock();
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int next_locked_block = 0;
|
int next_locked_block = 0;
|
||||||
for (int i = ph->offset / block_size; i < blocks_in_piece; ++i)
|
for (int i = offset / block_size; i < blocks_in_piece; ++i)
|
||||||
{
|
{
|
||||||
file::iovec_t iov;
|
file::iovec_t iov;
|
||||||
iov.iov_len = (std::min)(block_size, piece_size - ph->offset);
|
iov.iov_len = (std::min)(block_size, piece_size - offset);
|
||||||
|
|
||||||
if (next_locked_block < num_locked_blocks
|
if (next_locked_block < num_locked_blocks
|
||||||
&& locked_blocks[next_locked_block] == i)
|
&& locked_blocks[next_locked_block] == i)
|
||||||
{
|
{
|
||||||
++next_locked_block;
|
++next_locked_block;
|
||||||
TORRENT_PIECE_ASSERT(pe->blocks[i].buf, pe);
|
TORRENT_PIECE_ASSERT(pe->blocks[i].buf, pe);
|
||||||
TORRENT_PIECE_ASSERT(ph->offset == i * block_size, pe);
|
TORRENT_PIECE_ASSERT(offset == i * block_size, pe);
|
||||||
ph->offset += iov.iov_len;
|
offset += iov.iov_len;
|
||||||
ph->h.update(pe->blocks[i].buf, iov.iov_len);
|
ph->h.update(pe->blocks[i].buf, iov.iov_len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2436,9 +2444,9 @@ namespace libtorrent
|
||||||
|
|
||||||
time_point start_time = clock_type::now();
|
time_point start_time = clock_type::now();
|
||||||
|
|
||||||
TORRENT_PIECE_ASSERT(ph->offset == i * block_size, pe);
|
TORRENT_PIECE_ASSERT(offset == i * block_size, pe);
|
||||||
ret = j->storage->get_storage_impl()->readv(&iov, 1, j->piece
|
ret = j->storage->get_storage_impl()->readv(&iov, 1, j->piece
|
||||||
, ph->offset, file_flags, j->error);
|
, offset, file_flags, j->error);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
|
@ -2474,8 +2482,8 @@ namespace libtorrent
|
||||||
m_stats_counters.inc_stats_counter(counters::disk_job_time, read_time);
|
m_stats_counters.inc_stats_counter(counters::disk_job_time, read_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_PIECE_ASSERT(ph->offset == i * block_size, pe);
|
TORRENT_PIECE_ASSERT(offset == i * block_size, pe);
|
||||||
ph->offset += iov.iov_len;
|
offset += iov.iov_len;
|
||||||
ph->h.update(static_cast<char const*>(iov.iov_base), iov.iov_len);
|
ph->h.update(static_cast<char const*>(iov.iov_base), iov.iov_len);
|
||||||
|
|
||||||
l.lock();
|
l.lock();
|
||||||
|
@ -2486,6 +2494,8 @@ namespace libtorrent
|
||||||
|
|
||||||
l.lock();
|
l.lock();
|
||||||
|
|
||||||
|
ph->offset = offset;
|
||||||
|
|
||||||
// decrement the refcounts of the blocks we just hashed
|
// decrement the refcounts of the blocks we just hashed
|
||||||
for (int i = 0; i < num_locked_blocks; ++i)
|
for (int i = 0; i < num_locked_blocks; ++i)
|
||||||
m_disk_cache.dec_block_refcount(pe, locked_blocks[i], block_cache::ref_hashing);
|
m_disk_cache.dec_block_refcount(pe, locked_blocks[i], block_cache::ref_hashing);
|
||||||
|
|
Loading…
Reference in New Issue