From 790e0ab86e260f204d5fdf7b069e3335acc92b1b Mon Sep 17 00:00:00 2001 From: arvidn Date: Sun, 29 Sep 2024 12:57:39 +0200 Subject: [PATCH] raise the max piece size to 512 MiB and fix check when loading torrents --- ChangeLog | 1 + include/libtorrent/block_cache.hpp | 26 +++++++++++--------------- include/libtorrent/piece_picker.hpp | 4 ++-- src/block_cache.cpp | 5 ++--- src/torrent_info.cpp | 7 ++++++- test/test_torrent.cpp | 18 +++++++++++++----- 6 files changed, 35 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 919dc238e50..6f5cf643536 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * raise the max piece size to 512 MiB and fix check when loading torrents * back-port fix last_upload and last_download resume data fields to use posix time * back-port treat CGNAT address range as local IPs diff --git a/include/libtorrent/block_cache.hpp b/include/libtorrent/block_cache.hpp index 768a85ea040..5804d170074 100644 --- a/include/libtorrent/block_cache.hpp +++ b/include/libtorrent/block_cache.hpp @@ -235,40 +235,36 @@ namespace aux { // bitfield std::uint16_t blocks_in_piece = 0; - // this is the number of threads that are currently holding - // a reference to this piece. A piece may not be removed from - // the cache while this is > 0 - std::uint8_t piece_refcount = 0; - - // 8 bytes padding - - // ---- 64 bit boundary ---- + // the number of blocks in the cache for this piece + std::uint16_t num_blocks = 0; // the number of dirty blocks in this piece - std::uint32_t num_dirty:14; + std::uint16_t num_dirty = 0; - // the number of blocks in the cache for this piece - std::uint32_t num_blocks:14; + // this is the number of threads that are currently holding + // a reference to this piece. A piece may not be removed from + // the cache while this is > 0 + std::uint16_t piece_refcount:8; // while we have an outstanding async hash operation // working on this piece, 'hashing' is set to 1 // When the operation returns, this is set to 0. - std::uint32_t hashing:1; + std::uint16_t hashing:1; // if we've completed at least one hash job on this // piece, and returned it. This is set to one - std::uint32_t hashing_done:1; + std::uint16_t hashing_done:1; // if this is true, whenever refcount hits 0, // this piece should be deleted from the cache // (not just demoted) - std::uint32_t marked_for_deletion:1; + std::uint16_t marked_for_deletion:1; // this is set to true once we flush blocks past // the hash cursor. Once this happens, there's // no point in keeping cache blocks around for // it in avoid_readback mode - std::uint32_t need_readback:1; + std::uint16_t need_readback:1; // indicates which LRU list this piece is chained into enum cache_state_t diff --git a/include/libtorrent/piece_picker.hpp b/include/libtorrent/piece_picker.hpp index dec5c9f211c..df0de0aafbd 100644 --- a/include/libtorrent/piece_picker.hpp +++ b/include/libtorrent/piece_picker.hpp @@ -97,9 +97,9 @@ namespace libtorrent { // priority factor prio_factor = 3, // max blocks per piece - // there are counters in downloading_piece that only have 15 bits to + // there are counters in downloading_piece that only have 16 bits to // count blocks per piece, that's restricting this - max_blocks_per_piece = (1 << 15) - 1 + max_blocks_per_piece = (1 << 16) - 1 }; struct block_info diff --git a/src/block_cache.cpp b/src/block_cache.cpp index 0bcea98912f..6fd48077241 100644 --- a/src/block_cache.cpp +++ b/src/block_cache.cpp @@ -292,8 +292,7 @@ static_assert(int(job_action_name.size()) == static_cast(job_action_t::num_ #endif cached_piece_entry::cached_piece_entry() - : num_dirty(0) - , num_blocks(0) + : piece_refcount(0) , hashing(0) , hashing_done(0) , marked_for_deletion(false) @@ -790,7 +789,7 @@ bool block_cache::blocks_flushed(cached_piece_entry* pe, int const* flushed, int m_write_cache_size -= num_flushed; m_read_cache_size += num_flushed; - pe->num_dirty -= num_flushed; + pe->num_dirty = aux::numeric_cast(pe->num_dirty - num_flushed); update_cache_state(pe); return maybe_free_piece(pe); diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index 94a8c328526..7c3156b8c62 100644 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -1027,11 +1027,16 @@ namespace { // extract piece length std::int64_t piece_length = info.dict_find_int_value("piece length", -1); - if (piece_length <= 0 || piece_length > std::numeric_limits::max()) + if (piece_length <= 0) { ec = errors::torrent_missing_piece_length; return false; } + if (piece_length > std::numeric_limits::max()) + { + ec = errors::invalid_piece_size; + return false; + } file_storage files; files.set_piece_length(static_cast(piece_length)); diff --git a/test/test_torrent.cpp b/test/test_torrent.cpp index 3f308f91f7a..d31e7c40759 100644 --- a/test/test_torrent.cpp +++ b/test/test_torrent.cpp @@ -167,7 +167,7 @@ void test_running_torrent(std::shared_ptr info, std::int64_t file_ TEST_CHECK(h.get_file_priorities() == prio); } -void test_large_piece_size(int const size) +void test_large_piece_size(std::int64_t const size) { entry torrent; entry& info = torrent["info"]; @@ -179,7 +179,15 @@ void test_large_piece_size(int const size) std::vector buf; bencode(std::back_inserter(buf), torrent); add_torrent_params atp; - atp.ti = std::make_shared(buf, from_span); + try + { + atp.ti = std::make_shared(buf, from_span); + } + catch (lt::system_error const& e) + { + TEST_CHECK(e.code() == error_code(lt::errors::invalid_piece_size)); + return; + } atp.save_path = "."; lt::session ses; @@ -212,9 +220,9 @@ TORRENT_TEST(long_names) TORRENT_TEST(large_piece_size) { - test_large_piece_size(32768 * 16 * 1024); - test_large_piece_size(65536 * 16 * 1024); - test_large_piece_size(65537 * 16 * 1024); + test_large_piece_size(0x40000000 + 0x4000); + test_large_piece_size(0x80000000); + test_large_piece_size(0x100000000); } TORRENT_TEST(total_wanted)