"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "fsremap/src/work.t.hh" between
fstransform-0.9.3-src.tar.gz and fstransform-0.9.4.tar.gz

About: fstransform is a tool to change a file-system from one format to another, for example from jfs, xfs, or reiser to ext2, ext3, or ext4, in-place and without the need for backup.

work.t.hh  (fstransform-0.9.3-src):work.t.hh  (fstransform-0.9.4)
skipping to change at line 65 skipping to change at line 65
FC_FREE_SPACE = FT_IO_NS fr_io_posix::FC_FREE_SPACE, FC_FREE_SPACE = FT_IO_NS fr_io_posix::FC_FREE_SPACE,
FC_STORAGE = FT_IO_NS fr_io_posix::FC_STORAGE, FC_STORAGE = FT_IO_NS fr_io_posix::FC_STORAGE,
FC_PRIMARY_STORAGE = FT_IO_NS fr_io_posix::FC_PRIMARY_STORAGE, FC_PRIMARY_STORAGE = FT_IO_NS fr_io_posix::FC_PRIMARY_STORAGE,
FC_SECONDARY_STORAGE = FT_IO_NS fr_io_posix::FC_SECONDARY_STORAGE, FC_SECONDARY_STORAGE = FT_IO_NS fr_io_posix::FC_SECONDARY_STORAGE,
}; };
char const* const* const label = FT_IO_NS fr_io_posix::label; char const* const* const label = FT_IO_NS fr_io_posix::label;
char const* const label_LOOP_HOLES = "loop-holes"; char const* const label_LOOP_HOLES = "loop-holes";
template<typename T>
void fr_work<T>::show(const char * label1, const char * label2, ft_uoff effectiv
e_block_size,
const fr_map<T> & map, ft_log_level level)
{
ft_log_level header_level = level >= FC_DEBUG ? level : (ft_log_level)(level
+ 1);
if (!ff_log_is_enabled(header_level) && !ff_log_is_enabled(level))
return;
map_const_iterator iter = map.begin(), end = map.end();
ft_size n = map.size();
if (iter != end) {
ff_log(header_level, 0, "# %4"FT_ULL" extent%s in %s%s",
(ft_ull) n, (n == 1 ? " " : "s"), label1, label2);
if (ff_log_is_enabled(level)) {
ff_log(level, 0, "# effective block size = %"FT_ULL, (ft_ull) effect
ive_block_size);
show(level);
for (ft_size i = 0; iter != end; ++iter, ++i)
show(i, *iter, level);
}
} else {
ff_log(header_level, 0, "# no extents in %s%s", label1, label2);
}
ff_log(level, 0, "");
}
/** print extents header to log */
template<typename T>
void fr_work<T>::show(ft_log_level level)
{
ff_log(level, 0, "# extent physical logical length use
r_data");
}
/** print extent contents to log */
template<typename T>
void fr_work<T>::show(ft_size i, T physical, T logical, T length, ft_size user_d
ata, ft_log_level level)
{
ff_log(level, 0, "#%8"FT_ULL"\t%12"FT_ULL"\t%12"FT_ULL"\t%8"FT_ULL"\t(%"FT_U
LL")", (ft_ull)i,
(ft_ull) physical, (ft_ull) logical, (ft_ull) length, (ft_ull) user_d
ata);
}
/** default constructor */ /** default constructor */
template<typename T> template<typename T>
fr_work<T>::fr_work() fr_work<T>::fr_work()
: dev_map(), storage_map(), dev_free(), dev_transpose(), : dev_map(), storage_map(), dev_free(), dev_transpose(),
storage_free(), storage_transpose(), toclear_map(), storage_free(), storage_transpose(), toclear_map(),
eta(), work_total(0) io(NULL), eta(), work_total(0)
{ } { }
#ifdef FT_HAVE_EXTERNAL_TEMPLATE #ifdef FT_HAVE_EXTERNAL_TEMPLATE
/** /**
* copy constructor CANNOT be invoked, * copy constructor CANNOT be invoked,
* but some C++ compilers need it to be defined * but some C++ compilers need it to be defined
* if explicit template instantiation is used * if explicit template instantiation is used
*/ */
template<typename T> template<typename T>
fr_work<T>::fr_work(const fr_work<T> & other) fr_work<T>::fr_work(const fr_work<T> & other)
skipping to change at line 165 skipping to change at line 121
eta.clear(); eta.clear();
work_total = 0; work_total = 0;
} }
/** /**
* high-level do-everything method. calls in sequence init(), run() and cleanup( ). * high-level do-everything method. calls in sequence init(), run() and cleanup( ).
* return 0 if success, else error. * return 0 if success, else error.
*/ */
template<typename T> template<typename T>
int fr_work<T>::main(fr_vector<ft_uoff> & loop_file_extents, int fr_work<T>::main(fr_vector<ft_uoff> & loop_file_extents,
fr_vector<ft_uoff> & free_space_extents, FT_IO_NS fr_io & i fr_vector<ft_uoff> & free_space_extents,
o) fr_vector<ft_uoff> & to_zero_extents,
FT_IO_NS fr_io & io)
{ {
fr_work<T> worker; fr_work<T> worker;
return worker.run(loop_file_extents, free_space_extents, io); return worker.run(loop_file_extents, free_space_extents, to_zero_extents, io );
// worker.cleanup() is called automatically by destructor, no need to call e xplicitly // worker.cleanup() is called automatically by destructor, no need to call e xplicitly
} }
/** full remapping algorithm */ /** full remapping algorithm */
template<typename T> template<typename T>
int fr_work<T>::run(fr_vector<ft_uoff> & loop_file_extents, int fr_work<T>::run(fr_vector<ft_uoff> & loop_file_extents,
fr_vector<ft_uoff> & free_space_extents, FT_IO_NS fr_io & io fr_vector<ft_uoff> & free_space_extents,
) fr_vector<ft_uoff> & to_zero_extents,
FT_IO_NS fr_io & io)
{ {
int err; int err;
(err = init(io)) == 0 if ((err = init(io)) == 0
&& (err = analyze(loop_file_extents, free_space_extents)) == 0 && (err = analyze(loop_file_extents, free_space_extents, to_zero_extents
)) == 0
&& (err = create_storage()) == 0 && (err = create_storage()) == 0
&& (err = start_ui()) == 0 && (err = start_ui()) == 0
&& (err = relocate()) == 0 && (err = relocate()) == 0
&& (err = clear_free_space()) == 0 && (err = clear_free_space()) == 0
&& (err = close_storage_after_success()) == 0; && (err = close_storage_after_success()) == 0)
{ }
if (err == 0) { if (err == 0) {
ff_log(FC_NOTICE, 0, "%sjob completed.", io.simulate_run() ? "(simulated ) " : ""); ff_log(FC_NOTICE, 0, "%sjob completed.", io.simulate_run() ? "(simulated ) " : "");
} else if (!ff_log_is_reported(err)) { } else if (!ff_log_is_reported(err)) {
/* /*
* note 1.2.2) fr_remap.main() and other high-level *.main() methods * note 1.2.2) fr_remap.main() and other high-level *.main() methods
* must check for unreported errors and log them them with message * must check for unreported errors and log them them with message
* "failed with unreported error" * "failed with unreported error"
*/ */
skipping to change at line 304 skipping to change at line 265
* assumes that vectors are ordered by extent->logical, and modifies them * assumes that vectors are ordered by extent->logical, and modifies them
* in place: vector contents will be UNDEFINED when this method returns. * in place: vector contents will be UNDEFINED when this method returns.
* *
* basic implementation idea: to compute this->dev_map, performs in-place the un ion of specified * basic implementation idea: to compute this->dev_map, performs in-place the un ion of specified
* loop_file_extents and free_space_extents, then sorts in-place and complements such union. * loop_file_extents and free_space_extents, then sorts in-place and complements such union.
* *
* detailed implementation is quite complicated... see the comments and the docu mentation * detailed implementation is quite complicated... see the comments and the docu mentation
*/ */
template<typename T> template<typename T>
int fr_work<T>::analyze(fr_vector<ft_uoff> & loop_file_extents, int fr_work<T>::analyze(fr_vector<ft_uoff> & loop_file_extents,
fr_vector<ft_uoff> & free_space_extents) fr_vector<ft_uoff> & free_space_extents,
fr_vector<ft_uoff> & to_zero_extents)
{ {
// cleanup in case dev_map, storage_map or storage_map are not empty, or wor k_count != 0 // cleanup in case dev_map, storage_map or storage_map are not empty, or wor k_count != 0
cleanup(); cleanup();
map_type loop_map, loop_holes_map, renumbered_map; map_type loop_map, loop_holes_map, renumbered_map;
ft_uoff eff_block_size_log2 = io->effective_block_size_log2(); ft_uoff eff_block_size_log2 = io->effective_block_size_log2();
ft_uoff eff_block_size = (ft_uoff)1 << eff_block_size_log2; ft_uoff eff_block_size = (ft_uoff)1 << eff_block_size_log2;
ft_uoff dev_length = io->dev_length(); ft_uoff dev_length = io->dev_length();
/* /*
* algorithm: 1) find LOOP-FILE (logical) holes, i.e. LOOP-HOLES, * algorithm: 1) find LOOP-FILE (logical) holes, i.e. LOOP-HOLES,
* and store them in loop_holes_map * and store them in loop_holes_map
* note: all complement maps have physical == logical * note: all complement maps have physical == logical
*/ */
loop_holes_map.complement0_logical_shift(loop_file_extents, eff_block_size_l og2, dev_length); loop_holes_map.complement0_logical_shift(loop_file_extents, eff_block_size_l og2, dev_length);
if (io->job_clear() == FC_CLEAR_ALL) if (io->job_clear() == FC_CLEAR_ALL)
toclear_map = loop_holes_map; toclear_map = loop_holes_map;
// merge to_zero_extents into toclear_map
toclear_map.merge_shift(to_zero_extents, eff_block_size_log2, FC_PHYSICAL1);
/* algorithm: 0) compute LOOP-FILE extents and store in loop_map, sorted by physical */ /* algorithm: 0) compute LOOP-FILE extents and store in loop_map, sorted by physical */
loop_file_extents.sort_by_physical(); loop_file_extents.sort_by_physical();
loop_map.append0_shift(loop_file_extents, eff_block_size_log2); loop_map.append0_shift(loop_file_extents, eff_block_size_log2);
/* show LOOP-FILE extents sorted by physical */ /* show LOOP-FILE extents sorted by physical */
show(label[FC_LOOP_FILE], "", eff_block_size, loop_map); loop_map.show(label[FC_LOOP_FILE], "", eff_block_size);
/* algorithm: 0) compute FREE-SPACE extents and store in dev_free, sorted by physical /* algorithm: 0) compute FREE-SPACE extents and store in dev_free, sorted by physical
* *
* we must manually set ->logical = ->physical for all free_space_extents: * we must manually set ->logical = ->physical for all free_space_extents:
* here dev_free is just free space, but for I/O that computed it * here dev_free is just free space, but for I/O that computed it
* it could have been a ZERO-FILE with its own ->logical, * it could have been a ZERO-FILE with its own ->logical,
* *
* note: changing ->logical may also allow merging extents! * note: changing ->logical may also allow merging extents!
*/ */
{ {
skipping to change at line 351 skipping to change at line 316
physical = iter->first.physical >> eff_block_size_log2; physical = iter->first.physical >> eff_block_size_log2;
length = iter->second.length >> eff_block_size_log2; length = iter->second.length >> eff_block_size_log2;
dev_free.insert(physical, physical, length, FC_DEFAULT_USER_DATA); dev_free.insert(physical, physical, length, FC_DEFAULT_USER_DATA);
} }
} }
/* sanity check: LOOP-FILE and FREE-SPACE extents ->physical must NOT inters ect */ /* sanity check: LOOP-FILE and FREE-SPACE extents ->physical must NOT inters ect */
renumbered_map.intersect_all_all(loop_map, dev_free, FC_PHYSICAL1); renumbered_map.intersect_all_all(loop_map, dev_free, FC_PHYSICAL1);
if (!renumbered_map.empty()) { if (!renumbered_map.empty()) {
ff_log(FC_FATAL, 0, "inconsistent %s and %s: they share common blocks on %s !", label[FC_LOOP_FILE], label[FC_FREE_SPACE], label[FC_DEVICE]); ff_log(FC_FATAL, 0, "inconsistent %s and %s: they share common blocks on %s !", label[FC_LOOP_FILE], label[FC_FREE_SPACE], label[FC_DEVICE]);
show(label[FC_LOOP_FILE], " intersection with free-space", eff_block_siz e, renumbered_map, FC_DEBUG); renumbered_map.show(label[FC_LOOP_FILE], " intersection with free-space" , eff_block_size, FC_DEBUG);
return -EFAULT; return -EFAULT;
} }
/* /*
* move from LOOP-FILE to DEV-FREE and to TO-CLEAR-MAP * move from LOOP-FILE to DEV-FREE and to TO-CLEAR-MAP
* the (physical) extents in LOOP-FILE that are full with zeros (UNWRITTEN). * the (physical) extents in LOOP-FILE that are full with zeros (UNWRITTEN).
* *
* this converts FC_EXTENT_ZEROED extents into free extents, * this converts FC_EXTENT_ZEROED extents into free extents,
* and will also mark them to be cleared after relocate() finishes. * and will also mark them to be cleared after relocate() finishes.
*/ */
skipping to change at line 380 skipping to change at line 345
/* extent must be inserted in toclear_map even if io->job_clear( ) == FC_CLEAR_ALL */ /* extent must be inserted in toclear_map even if io->job_clear( ) == FC_CLEAR_ALL */
toclear_map.insert(physical, physical, length, FC_DEFAULT_USER_D ATA); toclear_map.insert(physical, physical, length, FC_DEFAULT_USER_D ATA);
dev_free.insert(physical, physical, length, FC_DEFAULT_USER_DATA ); dev_free.insert(physical, physical, length, FC_DEFAULT_USER_DATA );
tmp = iter; tmp = iter;
++iter; ++iter;
loop_map.remove(tmp); loop_map.remove(tmp);
} else } else
++iter; ++iter;
} }
} }
show("to-clear", " (initial)", eff_block_size, toclear_map, FC_DEBUG); toclear_map.show("to-clear", " (initial)", eff_block_size, FC_DEBUG);
show(label[FC_FREE_SPACE], " (after to-clear)", eff_block_size, dev_free); dev_free.show(label[FC_FREE_SPACE], " (after to-clear)", eff_block_size);
/* algorithm: 0) compute DEVICE extents /* algorithm: 0) compute DEVICE extents
* *
* how: compute physical complement of all LOOP-FILE and FREE-SPACE extents * how: compute physical complement of all LOOP-FILE and FREE-SPACE extents
* and assume they are used by DEVICE for its file-system * and assume they are used by DEVICE for its file-system
*/ */
/* compute in-place the union of LOOP-FILE extents and FREE-SPACE extents */ /* compute in-place the union of LOOP-FILE extents and FREE-SPACE extents */
loop_file_extents.append_all(free_space_extents); loop_file_extents.append_all(free_space_extents);
/* sort the union by physical: needed by dev_map.complement0_physical_shift( ) immediately below */ /* sort the union by physical: needed by dev_map.complement0_physical_shift( ) immediately below */
loop_file_extents.sort_by_physical(); loop_file_extents.sort_by_physical();
dev_map.complement0_physical_shift(loop_file_extents, eff_block_size_log2, d ev_length); dev_map.complement0_physical_shift(loop_file_extents, eff_block_size_log2, d ev_length);
/* show DEVICE extents sorted by physical */ /* show DEVICE extents sorted by physical */
show(label[FC_DEVICE], "", eff_block_size, dev_map); dev_map.show(label[FC_DEVICE], "", eff_block_size);
/* /*
* algorithm: 2), 3) allocate LOOP-HOLES for DEVICE extents logical destinat ion * algorithm: 2), 3) allocate LOOP-HOLES for DEVICE extents logical destinat ion
* and for LOOP-FILE invariant extents * and for LOOP-FILE invariant extents
*/ */
/* show LOOP-HOLES extents before allocation, sorted by physical */ /* show LOOP-HOLES extents before allocation, sorted by physical */
show(label_LOOP_HOLES, " (initial)", eff_block_size, loop_holes_map); loop_holes_map.show(label_LOOP_HOLES, " (initial)", eff_block_size);
/* algorithm: 2) re-number used DEVICE blocks, setting ->logical to values /* algorithm: 2) re-number used DEVICE blocks, setting ->logical to values
* from LOOP-HOLES. do not greedily use low hole numbers: * from LOOP-HOLES. do not greedily use low hole numbers:
* a) prefer holes with ->logical numbers equal to DEVICE ->physical block n umber: * a) prefer holes with ->logical numbers equal to DEVICE ->physical block n umber:
* they produce an INVARIANT block, already in its final destination * they produce an INVARIANT block, already in its final destination
* (marked with @@) * (marked with @@)
* b) spread the remaining ->logical across rest of holes (use best-fit allo cation) * b) spread the remaining ->logical across rest of holes (use best-fit allo cation)
*/ */
/* how: intersect dev_map and loop_holes_map and put result into renumbered_ map */ /* how: intersect dev_map and loop_holes_map and put result into renumbered_ map */
renumbered_map.intersect_all_all(dev_map, loop_holes_map, FC_BOTH); renumbered_map.intersect_all_all(dev_map, loop_holes_map, FC_BOTH);
/* show DEVICE INVARIANT extents (i.e. already in their final destination), sorted by physical */ /* show DEVICE INVARIANT extents (i.e. already in their final destination), sorted by physical */
show(label[FC_DEVICE], " (invariant)", eff_block_size, renumbered_map); renumbered_map.show(label[FC_DEVICE], " (invariant)", eff_block_size);
/* remove from dev_map all the INVARIANT extents in renumbered_map */ /* remove from dev_map all the INVARIANT extents in renumbered_map */
dev_map.remove_all(renumbered_map); dev_map.remove_all(renumbered_map);
/* /*
* also remove from loop_holes_map all extents in renumbered_map * also remove from loop_holes_map all extents in renumbered_map
* reason: they are no longer free (logical) holes, * reason: they are no longer free (logical) holes,
* since we allocated them for DEVICE INVARIANT extents * since we allocated them for DEVICE INVARIANT extents
*/ */
loop_holes_map.remove_all(renumbered_map); loop_holes_map.remove_all(renumbered_map);
/* /*
* then clear renumbered_map: its extents are already in their final destina tion * then clear renumbered_map: its extents are already in their final destina tion
* (they are INVARIANT) -> no work on them * (they are INVARIANT) -> no work on them
*/ */
renumbered_map.clear(); renumbered_map.clear();
/* show LOOP-HOLES (sorted by physical) after allocating DEVICE-INVARIANT ex tents */ /* show LOOP-HOLES (sorted by physical) after allocating DEVICE-INVARIANT ex tents */
show(label_LOOP_HOLES, " after device (invariant)", eff_block_size, loop_hol es_map); loop_holes_map.show(label_LOOP_HOLES, " after device (invariant)", eff_block _size);
/* /*
* algorithm: 2) b) spread the remaining DEVICE ->logical across rest of LOO P-HOLES * algorithm: 2) b) spread the remaining DEVICE ->logical across rest of LOO P-HOLES
* (use best-fit allocation) * (use best-fit allocation)
*/ */
/* order loop_holes_map by length */ /* order loop_holes_map by length */
fr_pool<T> loop_holes_pool(loop_holes_map); fr_pool<T> loop_holes_pool(loop_holes_map);
/* /*
* allocate LOOP-HOLES extents to store DEVICE extents using a best-fit stra tegy. * allocate LOOP-HOLES extents to store DEVICE extents using a best-fit stra tegy.
* move allocated extents from dev_map to renumbered_map * move allocated extents from dev_map to renumbered_map
*/ */
loop_holes_pool.allocate_all(dev_map, renumbered_map); loop_holes_pool.allocate_all(dev_map, renumbered_map);
/* show DEVICE RENUMBERED extents sorted by physical */ /* show DEVICE RENUMBERED extents sorted by physical */
show(label[FC_DEVICE], " (renumbered)", eff_block_size, renumbered_map); renumbered_map.show(label[FC_DEVICE], " (renumbered)", eff_block_size);
/* show LOOP-HOLES extents after allocation, sorted by physical */ /* show LOOP-HOLES extents after allocation, sorted by physical */
show(label_LOOP_HOLES, " (final)", eff_block_size, loop_holes_map); loop_holes_map.show(label_LOOP_HOLES, " (final)", eff_block_size);
/* sanity check */ /* sanity check */
if (!dev_map.empty()) { if (!dev_map.empty()) {
ff_log(FC_FATAL, 0, "internal error: there are extents in DEVICE not fit ting DEVICE. this is impossible! I give up"); ff_log(FC_FATAL, 0, "internal error: there are extents in DEVICE not fit ting DEVICE. this is impossible! I give up");
/* show DEVICE-NOTFITTING extents sorted by physical */ /* show DEVICE-NOTFITTING extents sorted by physical */
show(label[FC_DEVICE], " (not fitting)", eff_block_size, dev_map, FC_NOT ICE); dev_map.show(label[FC_DEVICE], " (not fitting)", eff_block_size, FC_NOTI CE);
return ENOSPC; return ENOSPC;
} }
/* move DEVICE (RENUMBERED) back into dev_map and clear renumbered_map */ /* move DEVICE (RENUMBERED) back into dev_map and clear renumbered_map */
dev_map.swap(renumbered_map); dev_map.swap(renumbered_map);
if (io->job_clear() == FC_CLEAR_MINIMAL) { if (io->job_clear() == FC_CLEAR_MINIMAL) {
/* /*
* also add DEVICE (RENUMBERED) to TO-CLEAR-MAP: * also add DEVICE (RENUMBERED) to TO-CLEAR-MAP:
* we MUST clear it once remapping is finished, * we MUST clear it once remapping is finished,
* since it contains data from the original device, NOT from the loop-fi le * since it contains data from the original device, NOT from the loop-fi le
skipping to change at line 475 skipping to change at line 440
renumbered_map.clear(); renumbered_map.clear();
renumbered_map.intersect_all_all(dev_transpose, toclear_map, FC_PHYSICAL 2); renumbered_map.intersect_all_all(dev_transpose, toclear_map, FC_PHYSICAL 2);
toclear_map.remove_all(renumbered_map); toclear_map.remove_all(renumbered_map);
iter = dev_transpose.begin(); iter = dev_transpose.begin();
end = dev_transpose.end(); end = dev_transpose.end();
for (; iter != end; ++iter) { for (; iter != end; ++iter) {
const map_value_type & extent = *iter; const map_value_type & extent = *iter;
toclear_map.insert(extent.first.physical, extent.first.physical, ext ent.second.length, FC_DEFAULT_USER_DATA); toclear_map.insert(extent.first.physical, extent.first.physical, ext ent.second.length, FC_DEFAULT_USER_DATA);
} }
dev_transpose.clear(); dev_transpose.clear();
show("to-clear", " (final)", eff_block_size, toclear_map, FC_DEBUG); toclear_map.show("to-clear", " (final)", eff_block_size, FC_DEBUG);
} }
/* /*
* 2.1) mark as INVARIANT (with @@) the (logical) extents in LOOP-FILE * 2.1) mark as INVARIANT (with @@) the (logical) extents in LOOP-FILE
* already in their final destination, and forget them (no work on those). * already in their final destination, and forget them (no work on those).
* also compute total length of extents remaining in LOOP-FILE and store in work_count. * also compute total length of extents remaining in LOOP-FILE and store in work_count.
*/ */
iter = loop_map.begin(); iter = loop_map.begin();
end = loop_map.end(); end = loop_map.end();
T work_count = 0; /**< number of blocks to be relocated */ T work_count = 0; /**< number of blocks to be relocated */
skipping to change at line 507 skipping to change at line 472
work_count += iter->second.length; work_count += iter->second.length;
/* /*
* also prepare for item 3) "merge renumbered DEVICE extents with re maining LOOP-FILE extents" * also prepare for item 3) "merge renumbered DEVICE extents with re maining LOOP-FILE extents"
* i.e. remember who's who * i.e. remember who's who
*/ */
iter->second.user_data = FC_LOOP_FILE; iter->second.user_data = FC_LOOP_FILE;
++iter; ++iter;
} }
} }
/* show LOOP-FILE (INVARIANT) blocks, sorted by physical */ /* show LOOP-FILE (INVARIANT) blocks, sorted by physical */
show(label[FC_LOOP_FILE], " (invariant)", eff_block_size, renumbered_map); renumbered_map.show(label[FC_LOOP_FILE], " (invariant)", eff_block_size);
/* then forget them */ /* then forget them */
renumbered_map.clear(); renumbered_map.clear();
/* /*
* algorithm: 3) merge renumbered DEVICE extents with LOOP-FILE blocks (reme mber who's who) * algorithm: 3) merge renumbered DEVICE extents with LOOP-FILE blocks (reme mber who's who)
* also compute total length of extents remaining in DEVICE and add it to wo rk_count. * also compute total length of extents remaining in DEVICE and add it to wo rk_count.
*/ */
iter = dev_map.begin(); iter = dev_map.begin();
end = dev_map.end(); end = dev_map.end();
for (; iter != end; ++iter) { for (; iter != end; ++iter) {
skipping to change at line 531 skipping to change at line 496
} }
dev_map.clear(); dev_map.clear();
/* /*
* from now on, we only need one of dev_map or loop_map, not both. * from now on, we only need one of dev_map or loop_map, not both.
* we choose dev_map: more intuitive name, and already stored in 'this' * we choose dev_map: more intuitive name, and already stored in 'this'
*/ */
dev_map.swap(loop_map); dev_map.swap(loop_map);
dev_map.total_count(work_count); dev_map.total_count(work_count);
dev_map.used_count(work_count); dev_map.used_count(work_count);
/* show DEVICE + LOOP-FILE extents after merge, sorted by physical */ /* show DEVICE + LOOP-FILE extents after merge, sorted by physical */
show("device + loop-file", " (merged)", eff_block_size, dev_map); dev_map.show("device + loop-file", " (merged)", eff_block_size);
double pretty_len = 0.0; double pretty_len = 0.0;
const char * pretty_unit = ff_pretty_size((ft_uoff) work_count << eff_block_ size_log2, & pretty_len); const char * pretty_unit = ff_pretty_size((ft_uoff) work_count << eff_block_ size_log2, & pretty_len);
ff_log(FC_NOTICE, 0, "analysis completed: %.2f %sbytes must be relocated", p retty_len, pretty_unit); ff_log(FC_NOTICE, 0, "analysis completed: %.2f %sbytes must be relocated", p retty_len, pretty_unit);
/* /*
* algorithm: 4) compute (physical) intersection of FREE-SPACE and LOOP-HOLE S, * algorithm: 4) compute (physical) intersection of FREE-SPACE and LOOP-HOLE S,
* and mark it as FREE-SPACE (INVARIANT) (with !!). * and mark it as FREE-SPACE (INVARIANT) (with !!).
* we can use these extents as partial or total replacement for STORAGE - se e 5) * we can use these extents as partial or total replacement for STORAGE - se e 5)
skipping to change at line 568 skipping to change at line 533
/* /*
* consider for PRIMARY-STORAGE only "relatively large" blocks, i.e. * consider for PRIMARY-STORAGE only "relatively large" blocks, i.e.
* 1) at least 1024 * PAGE_SIZE bytes long, or at least work_count / 1024 bl ocks long * 1) at least 1024 * PAGE_SIZE bytes long, or at least work_count / 1024 bl ocks long
* 2) in any case, at least 1 * PAGE_SIZE bytes long * 2) in any case, at least 1 * PAGE_SIZE bytes long
*/ */
ft_uoff hole_threshold = ff_max2((ft_uoff)page_size_blocks, ff_min2((ft_uoff ) work_count >> 10, (ft_uoff) page_size << 10 >> eff_block_size_log2)); ft_uoff hole_threshold = ff_max2((ft_uoff)page_size_blocks, ff_min2((ft_uoff ) work_count >> 10, (ft_uoff) page_size << 10 >> eff_block_size_log2));
T hole_len, hole_total_len = 0; T hole_len, hole_total_len = 0;
iter = renumbered_map.begin(); iter = renumbered_map.begin();
end = renumbered_map.end(); end = renumbered_map.end();
show(label[FC_FREE_SPACE], " (invariant)", eff_block_size, renumbered_map); renumbered_map.show(label[FC_FREE_SPACE], " (invariant)", eff_block_size);
while (iter != end) { while (iter != end) {
map_value_type & extent = *iter; map_value_type & extent = *iter;
/* /*
* whether this hole (extent from dev_free) is large enough to be useful or not, * whether this hole (extent from dev_free) is large enough to be useful or not,
* it is invariant free space. the current remapping algorithm will neve r use it, * it is invariant free space. the current remapping algorithm will neve r use it,
* so remove it from free space to get accurate calculation of usable fr ee space. * so remove it from free space to get accurate calculation of usable fr ee space.
*/ */
dev_free.remove(extent); dev_free.remove(extent);
if ((ft_uoff) (hole_len = iter->second.length) >= hole_threshold) { if ((ft_uoff) (hole_len = iter->second.length) >= hole_threshold) {
skipping to change at line 597 skipping to change at line 562
tmp = iter; tmp = iter;
++iter; ++iter;
renumbered_map.remove(tmp); renumbered_map.remove(tmp);
} }
/* /*
* move FREE-SPACE (INVARIANT) extents into storage_map (i.e. PRIMARY-STORAG E), * move FREE-SPACE (INVARIANT) extents into storage_map (i.e. PRIMARY-STORAG E),
* as the latter is stored into 'this' * as the latter is stored into 'this'
*/ */
storage_map.swap(renumbered_map); storage_map.swap(renumbered_map);
/* show PRIMARY-STORAGE extents, sorted by physical */ /* show PRIMARY-STORAGE extents, sorted by physical */
show(label[FC_PRIMARY_STORAGE], " (= free-space, invariant, contiguous, alig ned)", eff_block_size, storage_map); storage_map.show(label[FC_PRIMARY_STORAGE], " (= free-space, invariant, cont iguous, aligned)", eff_block_size);
pretty_len = 0.0; pretty_len = 0.0;
pretty_unit = ff_pretty_size((ft_uoff) hole_total_len << eff_block_size_log2 , & pretty_len); pretty_unit = ff_pretty_size((ft_uoff) hole_total_len << eff_block_size_log2 , & pretty_len);
ft_size storage_map_n = storage_map.size(); ft_size storage_map_n = storage_map.size();
ff_log(FC_INFO, 0, "%s: located %.2f %sbytes (%"FT_ULL" fragment%s) usable i n %s (free, invariant, contiguous and aligned)", ff_log(FC_INFO, 0, "%s: located %.2f %sbytes (%" FT_ULL " fragment%s) usable in %s (free, invariant, contiguous and aligned)",
label[FC_PRIMARY_STORAGE], pretty_len, pretty_unit, (ft_ull)storage_m ap_n, (storage_map_n == 1 ? "" : "s"), label[FC_DEVICE]); label[FC_PRIMARY_STORAGE], pretty_len, pretty_unit, (ft_ull)storage_m ap_n, (storage_map_n == 1 ? "" : "s"), label[FC_DEVICE]);
storage_map.total_count(hole_total_len); storage_map.total_count(hole_total_len);
/* all done */ /* all done */
return 0; return 0;
} }
static int unusable_storage_size(const char * label, ft_uoff requested_len, cons t char * type_descr, ft_ull type_bytes) static int unusable_storage_size(const char * label, ft_uoff requested_len, cons t char * type_descr, ft_ull type_bytes)
{ {
ff_log(FC_FATAL, 0, "fatal error: cannot use job %s length = %"FT_ULL" bytes , it is incompatible with %s = %"FT_ULL" bytes," ff_log(FC_FATAL, 0, "fatal error: cannot use job %s length = %" FT_ULL " byt es, it is incompatible with %s = %" FT_ULL " bytes,"
" original job was probably created on a platform with %s", " original job was probably created on a platform with %s",
label, (ft_ull) requested_len, type_descr, type_bytes); label, (ft_ull) requested_len, type_descr, type_bytes);
/* mark error as reported */ /* mark error as reported */
return -EOVERFLOW; return -EOVERFLOW;
} }
/** /**
* creates on-disk secondary storage, used as (hopefully small) backup area duri ng relocate(). * creates on-disk secondary storage, used as (hopefully small) backup area duri ng relocate().
* must be executed before relocate() * must be executed before relocate()
*/ */
skipping to change at line 696 skipping to change at line 661
const char * req_label = label[req_total_size_exact != 0 ? FC_STORAGE : FC_SECONDARY_STORAGE]; const char * req_label = label[req_total_size_exact != 0 ? FC_STORAGE : FC_SECONDARY_STORAGE];
double req_pretty_len = 0.0; double req_pretty_len = 0.0;
const char * req_pretty_unit = ff_pretty_size(req_len, & req_pretty_len) ; const char * req_pretty_unit = ff_pretty_size(req_len, & req_pretty_len) ;
if (free_ram_or_0 == 0) { if (free_ram_or_0 == 0) {
ff_log(FC_WARN, 0, "no idea if the %.2f %sbytes requested for %s%s w ill fit into free RAM", ff_log(FC_WARN, 0, "no idea if the %.2f %sbytes requested for %s%s w ill fit into free RAM",
req_pretty_len, req_pretty_unit, "mmapped() ", req_label); req_pretty_len, req_pretty_unit, "mmapped() ", req_label);
ff_log(FC_WARN, 0, "continuing, but troubles (memory exhaustion) are possible"); ff_log(FC_WARN, 0, "continuing, but troubles (memory exhaustion) are possible");
} else if ((ft_uoff) req_len >= free_ram_or_0 / 2) { } else if ((ft_uoff) req_len >= free_ram_or_0 / 2) {
ff_log(FC_WARN, 0, "using %.2f %sbytes as requested for %s, but only ff_log(FC_WARN, 0, "using %.2f %sbytes as requested for %s%s, but on
%.2f %sbytes RAM are free", ly %.2f %sbytes RAM are free",
req_pretty_len, req_pretty_unit, req_label, free_pretty_len, req_pretty_len, req_pretty_unit, "mmapped() ", req_label, fr
free_pretty_unit); ee_pretty_len, free_pretty_unit);
ff_log(FC_WARN, 0, "honoring the request, but expect troubles (memor y exhaustion)"); ff_log(FC_WARN, 0, "honoring the request, but expect troubles (memor y exhaustion)");
} }
} }
if (req_total_size_exact == 0) { if (req_total_size_exact == 0) {
/* /*
* auto-detect total storage size to use: * auto-detect total storage size to use:
* we want it to be the smallest between * we want it to be the smallest between
* 50% of free RAM (if free RAM cannot be determined, use 16 MB on 32b it platforms, and 256MB on 64bit+ platforms) * 50% of free RAM (if free RAM cannot be determined, use 16 MB on 32b it platforms, and 256MB on 64bit+ platforms)
* 12.5% of bytes to relocate * 12.5% of bytes to relocate
*/ */
skipping to change at line 808 skipping to change at line 773
ff_log(FC_WARN, 0, "%s size to use would be 0 bytes, increasing to %.2f %sbytes", ff_log(FC_WARN, 0, "%s size to use would be 0 bytes, increasing to %.2f %sbytes",
"memory buffer", mem_pretty_len, mem_pretty_unit); "memory buffer", mem_pretty_len, mem_pretty_unit);
} }
ft_size primary_size; ft_size primary_size;
if (req_primary_size_exact > avail_primary_size) { if (req_primary_size_exact > avail_primary_size) {
double avail_pretty_len = 0.0, req_pretty_len = 0.0; double avail_pretty_len = 0.0, req_pretty_len = 0.0;
const char * avail_pretty_unit = ff_pretty_size(avail_primary_size, & av ail_pretty_len); const char * avail_pretty_unit = ff_pretty_size(avail_primary_size, & av ail_pretty_len);
const char * req_pretty_unit = ff_pretty_size(req_primary_size_exact, & req_pretty_len); const char * req_pretty_unit = ff_pretty_size(req_primary_size_exact, & req_pretty_len);
ff_log(FC_ERROR, 0, "available %s is only %"FT_ULL" bytes (%.2f %sbytes) ff_log(FC_ERROR, 0, "available %s is only %" FT_ULL " bytes (%.2f %sbyte
," s),"
" too small for requested %"FT_ULL" bytes (%.2f %sbytes)", label[ " too small for requested %" FT_ULL " bytes (%.2f %sbytes)", labe
FC_PRIMARY_STORAGE], l[FC_PRIMARY_STORAGE],
(ft_ull)avail_primary_size, avail_pretty_len, avail_pretty_unit, (ft_ull)avail_primary_size, avail_pretty_len, avail_pretty_unit,
(ft_ull) req_primary_size_exact, req_pretty_len, req_pretty_unit) ; (ft_ull) req_primary_size_exact, req_pretty_len, req_pretty_unit) ;
/* mark error as reported */ /* mark error as reported */
return -ENOSPC; return -ENOSPC;
} else if (req_primary_size_exact != 0) } else if (req_primary_size_exact != 0)
primary_size = req_primary_size_exact; primary_size = req_primary_size_exact;
else else
primary_size = ff_min2(avail_primary_size, auto_total_size); primary_size = ff_min2(avail_primary_size, auto_total_size);
ft_size secondary_size; ft_size secondary_size;
skipping to change at line 921 skipping to change at line 886
storage_map.clear(); storage_map.clear();
storage_map.append0_shift(primary_storage, eff_block_size_log2); storage_map.append0_shift(primary_storage, eff_block_size_log2);
} }
storage_map.total_count((T)(primary_len >> eff_block_size_log2)); storage_map.total_count((T)(primary_len >> eff_block_size_log2));
double pretty_len = 0.0; double pretty_len = 0.0;
const char * pretty_unit = ff_pretty_size(primary_len, & pretty_len); const char * pretty_unit = ff_pretty_size(primary_len, & pretty_len);
ft_size fragment_n = primary_storage.size(); ft_size fragment_n = primary_storage.size();
ff_log(FC_INFO, 0, "%s: actually using %.2f %sbytes (%"FT_ULL" fragment%s) f rom %s", ff_log(FC_INFO, 0, "%s: actually using %.2f %sbytes (%" FT_ULL " fragment%s) from %s",
label[FC_PRIMARY_STORAGE], pretty_len, pretty_unit, label[FC_PRIMARY_STORAGE], pretty_len, pretty_unit,
(ft_ull)fragment_n, (fragment_n == 1 ? "" : "s"), label[FC_DEVICE]); (ft_ull)fragment_n, (fragment_n == 1 ? "" : "s"), label[FC_DEVICE]);
show(label[FC_PRIMARY_STORAGE], " (actually used)", (ft_uoff) 1 << eff_block _size_log2, storage_map); storage_map.show(label[FC_PRIMARY_STORAGE], " (actually used)", (ft_uoff) 1 << eff_block_size_log2);
} }
/** start UI, passing I/O object to it. requires I/O to know device length and s torage size */ /** start UI, passing I/O object to it. requires I/O to know device length and s torage size */
template<typename T> template<typename T>
int fr_work<T>::start_ui() int fr_work<T>::start_ui()
{ {
FT_UI_NS fr_ui * ui = io->ui(); FT_UI_NS fr_ui * ui = io->ui();
int err = 0; int err = 0;
if (ui != NULL) if (ui != NULL)
err = ui->start(io); err = ui->start(io);
skipping to change at line 1073 skipping to change at line 1038
const ft_uoff eff_block_size_log2 = io->effective_block_size_log2(); const ft_uoff eff_block_size_log2 = io->effective_block_size_log2();
T dev_used = dev_map.used_count(), storage_used = storage_map.used_count(); T dev_used = dev_map.used_count(), storage_used = storage_map.used_count();
ft_uoff total_len = ((ft_uoff)dev_used + (ft_uoff)storage_used) << eff_block _size_log2; ft_uoff total_len = ((ft_uoff)dev_used + (ft_uoff)storage_used) << eff_block _size_log2;
double percentage = 0.0, time_left = -1.0; double percentage = 0.0, time_left = -1.0;
if (work_total != 0) { if (work_total != 0) {
percentage = 1.0 - ((double)dev_used + 0.5 * (double)storage_used) / (do uble)work_total; percentage = 1.0 - ((double)dev_used + 0.5 * (double)storage_used) / (do uble)work_total;
if (simul_msg[0] == '\0') /* underestimate the progress percentage: algorithm slows down near the
time_left = eta.add(percentage); end */
else /* time_left = eta.add(percentage); */
eta.clear(); double x = percentage;
time_left = eta.add(0.5*x + 0.5*x*x);
percentage *= 100.0; percentage *= 100.0;
} }
ff_show_progress(log_level, simul_msg, percentage, total_len, " still to rel ocate", time_left); ff_show_progress(log_level, simul_msg, percentage, total_len, " still to rem ap", time_left);
const ft_uoff eff_block_size = (ft_uoff)1 << eff_block_size_log2; const ft_uoff eff_block_size = (ft_uoff)1 << eff_block_size_log2;
show(label[FC_DEVICE], "", eff_block_size, dev_map, FC_DUMP); dev_map.show(label[FC_DEVICE], "", eff_block_size, FC_DUMP);
show(label[FC_DEVICE], " free space", eff_block_size, dev_free, FC_DUMP); dev_free.show(label[FC_DEVICE], " free space", eff_block_size, FC_DUMP);
show(label[FC_STORAGE], "", eff_block_size, storage_map, FC_DUMP); storage_map.show(label[FC_STORAGE], "", eff_block_size, FC_DUMP);
show(label[FC_STORAGE], " free space", eff_block_size, storage_free, FC_DUMP storage_free.show(label[FC_STORAGE], " free space", eff_block_size, FC_DUMP)
); ;
} }
/** /**
* called once by relocate() immediately before starting the remapping phase. * called once by relocate() immediately before starting the remapping phase.
* *
* 1) check that last device block to be written is actually writable. * 1) check that last device block to be written is actually writable.
* Reason: at least on Linux, if a filesystems is smaller than its containing device, * Reason: at least on Linux, if a filesystems is smaller than its containing device,
* it often limits to its length the writable blocks in the device. * it often limits to its length the writable blocks in the device.
* *
* 2) check for corner care where we have an odd-sized (i.e. smaller than effect ive block size) last device block, * 2) check for corner care where we have an odd-sized (i.e. smaller than effect ive block size) last device block,
skipping to change at line 1122 skipping to change at line 1088
ft_uoff dev_len = io->dev_length(), loop_file_len = io->loop_file_length(); ft_uoff dev_len = io->dev_length(), loop_file_len = io->loop_file_length();
dev_len &= ~(eff_block_size - 1); dev_len &= ~(eff_block_size - 1);
if (loop_file_len <= dev_len) if (loop_file_len <= dev_len)
return io->check_last_block(); return io->check_last_block();
ft_uoff odd_block_len = loop_file_len & (eff_block_size - 1); ft_uoff odd_block_len = loop_file_len & (eff_block_size - 1);
const char * simul_msg = io->simulate_run() ? "(simulated) " : ""; const char * simul_msg = io->simulate_run() ? "(simulated) " : "";
ff_log(FC_ERROR, 0, "%s%s has an odd-sized last block (%"FT_ULL" bytes long) that exceeds device rounded length.", ff_log(FC_ERROR, 0, "%s%s has an odd-sized last block (%" FT_ULL " bytes lon g) that exceeds device rounded length.",
simul_msg, label[FC_LOOP_FILE], (ft_ull) odd_block_len); simul_msg, label[FC_LOOP_FILE], (ft_ull) odd_block_len);
ff_log(FC_ERROR, 0, "%sExiting, please shrink %s to %"FT_ULL" bytes or less before running fsremap again.", ff_log(FC_ERROR, 0, "%sExiting, please shrink %s to %" FT_ULL " bytes or les s before running fsremap again.",
simul_msg, label[FC_LOOP_FILE], (ft_ull) dev_len); simul_msg, label[FC_LOOP_FILE], (ft_ull) dev_len);
return -EFBIG; return -EFBIG;
} }
/** called by relocate(). move as many extents as possible from DEVICE to STORAG E */ /** called by relocate(). move as many extents as possible from DEVICE to STORAG E */
template<typename T> template<typename T>
int fr_work<T>::fill_storage() int fr_work<T>::fill_storage()
{ {
map_iterator from_iter = dev_map.begin(), from_pos, from_end = dev_map.end() ; map_iterator from_iter = dev_map.begin(), from_pos, from_end = dev_map.end() ;
T moved = 0, from_used_count = dev_map.used_count(), to_free_count = storage _map.free_count(); T moved = 0, from_used_count = dev_map.used_count(), to_free_count = storage _map.free_count();
const bool simulated = io->simulate_run(); const bool simulated = io->simulate_run();
const bool replaying = io->is_replaying(); const bool replaying = io->is_replaying();
const char * simul_msg = simulated ? "(simulated) " : replaying ? "(replayin g) " : ""; const char * simul_msg = simulated ? "(simulated) " : replaying ? "(replayin g) " : "";
double pretty_len = 0.0; double pretty_len = 0.0;
const char * pretty_label = ff_pretty_size((ft_uoff)ff_min2<T>(from_used_cou nt, to_free_count) const char * pretty_label = ff_pretty_size((ft_uoff)ff_min2<T>(from_used_cou nt, to_free_count)
<< io->effective_block_size_log2( ), & pretty_len); << io->effective_block_size_log2( ), & pretty_len);
ff_log(FC_INFO, 0, "%sfilling %s by moving %.2f %sbytes from %s ...", ff_log(FC_INFO, 0, "%sfilling %s by moving %.2f %sbytes from %s ...",
simul_msg, label[FC_STORAGE], pretty_len, pretty_label, label[FC_DEVI CE]); simul_msg, label[FC_STORAGE], pretty_len, pretty_label, label[FC_DEVI CE]);
show(); /* show extents header */ fr_extent<T>::show(); /* show extents header */
ft_size counter = 0; ft_size counter = 0;
int err = 0; int err = 0;
while (err == 0 && moved < to_free_count && from_iter != from_end) { while (err == 0 && moved < to_free_count && from_iter != from_end) {
/* fully or partially move this extent to STORAGE */ /* fully or partially move this extent to STORAGE */
from_pos = from_iter; from_pos = from_iter;
++from_iter; ++from_iter;
/* note: some blocks may have been moved even in case of errors! */ /* note: some blocks may have been moved even in case of errors! */
err = move(counter++, from_pos, FC_DEV2STORAGE, moved); err = move(counter++, from_pos, FC_DEV2STORAGE, moved);
} }
skipping to change at line 1184 skipping to change at line 1150
int fr_work<T>::move(ft_size counter, map_iterator from_iter, fr_dir dir, T & re t_moved) int fr_work<T>::move(ft_size counter, map_iterator from_iter, fr_dir dir, T & re t_moved)
{ {
T moved, length = from_iter->second.length; T moved, length = from_iter->second.length;
const bool is_to_dev = ff_is_to_dev(dir); const bool is_to_dev = ff_is_to_dev(dir);
map_stat_type & to_map = is_to_dev ? dev_map : storage_map; map_stat_type & to_map = is_to_dev ? dev_map : storage_map;
map_type & to_free_map = is_to_dev ? dev_free : storage_free; map_type & to_free_map = is_to_dev ? dev_free : storage_free;
map_iterator to_free_iter = to_free_map.begin(), to_free_pos, to_free_end = to_free_map.end(); map_iterator to_free_iter = to_free_map.begin(), to_free_pos, to_free_end = to_free_map.end();
int err = 0; int err = 0;
if (ff_log_is_enabled((ft_log_level)FC_SHOW_DEFAULT_LEVEL)) { if (ff_logl_is_enabled("extent", 6/*strlen("extent")*/, FC_SHOW_DEFAULT_LEVE L)) {
const map_value_type & extent = *from_iter; const map_value_type & extent = *from_iter;
show(counter, extent.first.physical, extent.second.logical, fr_extent<T>::show(counter, extent.first.physical, extent.second.logical
ff_min2(extent.second.length, to_map.free_count()), ,
extent.second.user_data); ff_min2(extent.second.length, to_map.free_count()),
extent.second.user_data);
} }
while (err == 0 && length != 0 && to_free_iter != to_free_end) { while (err == 0 && length != 0 && to_free_iter != to_free_end) {
to_free_pos = to_free_iter; to_free_pos = to_free_iter;
++to_free_iter; ++to_free_iter;
moved = 0; moved = 0;
err = move_fragment(from_iter, to_free_pos, dir, moved); err = move_fragment(from_iter, to_free_pos, dir, moved);
length -= moved; length -= moved;
ret_moved += moved; ret_moved += moved;
} }
skipping to change at line 1297 skipping to change at line 1263
int err = 0; int err = 0;
const bool simulated = io->simulate_run(); const bool simulated = io->simulate_run();
const char * simul_msg = simulated ? "(simulated) " : io->is_replaying() ? " (replaying) " : ""; const char * simul_msg = simulated ? "(simulated) " : io->is_replaying() ? " (replaying) " : "";
/* find all DEVICE or STORAGE extents that can be moved to their final desti nation into DEVICE free space */ /* find all DEVICE or STORAGE extents that can be moved to their final desti nation into DEVICE free space */
movable.intersect_all_all(from_transpose, dev_free, FC_PHYSICAL1); movable.intersect_all_all(from_transpose, dev_free, FC_PHYSICAL1);
if (movable.empty()) { if (movable.empty()) {
ff_log(FC_INFO, 0, "%smoved 0 bytes from %s to target (not so useful)", simul_msg, label_from); ff_log(FC_INFO, 0, "%smoved 0 bytes from %s to target (not so useful)", simul_msg, label_from);
ft_uoff eff_block_size = (ft_uoff)1 << io->effective_block_size_log2(); ft_uoff eff_block_size = (ft_uoff)1 << io->effective_block_size_log2();
show(label_from, " transposed", eff_block_size, from_transpose, FC_DEBUG from_transpose.show(label_from, " transposed", eff_block_size);
); dev_free.show(label[FC_DEVICE], " free space", eff_block_size);
show(label[FC_DEVICE], " free space", eff_block_size, dev_free, FC_DEBUG
);
return err; return err;
} }
if (ff_log_is_enabled(FC_INFO)) { if (ff_log_is_enabled(FC_INFO)) {
map_const_iterator iter = movable.begin(), end = movable.end(); map_const_iterator iter = movable.begin(), end = movable.end();
ft_uoff movable_length = 0; ft_uoff movable_length = 0;
for (; iter != end; ++iter) for (; iter != end; ++iter)
movable_length += iter->second.length; movable_length += iter->second.length;
movable_length <<= io->effective_block_size_log2(); movable_length <<= io->effective_block_size_log2();
double pretty_len = 0.0; double pretty_len = 0.0;
const char * pretty_label = ff_pretty_size(movable_length, & pretty_len) ; const char * pretty_label = ff_pretty_size(movable_length, & pretty_len) ;
ff_log(FC_INFO, 0, "%smoving %.2f %sbytes from %s to target ...", ff_log(FC_INFO, 0, "%smoving %.2f %sbytes from %s to target ...",
simul_msg, pretty_len, pretty_label, label_from); simul_msg, pretty_len, pretty_label, label_from);
show(); /* show extents header */ fr_extent<T>::show(); /* show extents header */
} }
/* move them */ /* move them */
map_const_iterator iter = movable.begin(), end = movable.end(); map_const_iterator iter = movable.begin(), end = movable.end();
T from_physical, to_physical, length; T from_physical, to_physical, length;
ft_size counter = 0; ft_size counter = 0;
for (; iter != end; ++iter) { for (; iter != end; ++iter) {
const map_value_type & extent = *iter; const map_value_type & extent = *iter;
from_physical = extent.second.logical; from_physical = extent.second.logical;
to_physical = extent.first.physical; to_physical = extent.first.physical;
length = extent.second.length; length = extent.second.length;
/* sequential disk access: consecutive calls to io->copy() are sorted by to_physical, i.e. device to_offset */ /* sequential disk access: consecutive calls to io->copy() are sorted by to_physical, i.e. device to_offset */
err = io->copy(dir, from_physical, to_physical, length); err = io->copy(dir, from_physical, to_physical, length);
show(counter++, from_physical, to_physical, length, extent.second.user_d ata); fr_extent<T>::show(counter++, from_physical, to_physical, length, extent .second.user_data);
if (err != 0) if (err != 0)
return err; return err;
from_transpose.remove(extent); from_transpose.remove(extent);
from_map.stat_remove(from_physical, to_physical, length); from_map.stat_remove(from_physical, to_physical, length);
from_free.insert(from_physical, from_physical, length, FC_DEFAULT_USER_D ATA); from_free.insert(from_physical, from_physical, length, FC_DEFAULT_USER_D ATA);
/* /*
* forget final destination extent: it's NOT free anymore, but nothing t o do there. * forget final destination extent: it's NOT free anymore, but nothing t o do there.
* actually, if it is DEVICE-RENUMBERED, it will likely be cleared after relocate() finishes, * actually, if it is DEVICE-RENUMBERED, it will likely be cleared after relocate() finishes,
* but in such case it is supposed to be ALREADY in toclear_map * but in such case it is supposed to be ALREADY in toclear_map
*/ */
skipping to change at line 1373 skipping to change at line 1339
int err = 0; int err = 0;
fr_clear_free_space job_clear = io->job_clear(); fr_clear_free_space job_clear = io->job_clear();
do { do {
ft_uoff toclear_len = 0; ft_uoff toclear_len = 0;
if (job_clear == FC_CLEAR_MINIMAL) if (job_clear == FC_CLEAR_MINIMAL)
toclear_len += (ft_uoff) io->job_storage_size(FC_PRIMARY_STORAGE_EXA CT_SIZE); toclear_len += (ft_uoff) io->job_storage_size(FC_PRIMARY_STORAGE_EXA CT_SIZE);
map_const_iterator iter = toclear_map.begin(), end = toclear_map.end(); map_const_iterator iter = toclear_map.begin(), end = toclear_map.end();
for (; iter != end; ++iter) for (; iter != end; ++iter)
toclear_len += iter->second.length << io->effective_block_size_log2( ); toclear_len += (ft_uoff) iter->second.length << io->effective_block_ size_log2();
double pretty_len = 0.0; double pretty_len = 0.0;
const char * pretty_label = ff_pretty_size(toclear_len, & pretty_len); const char * pretty_label = ff_pretty_size(toclear_len, & pretty_len);
switch (job_clear) { switch (job_clear) {
case FC_CLEAR_MINIMAL: case FC_CLEAR_MINIMAL:
ff_log(FC_NOTICE, 0, "%sclearing %.2f %sbytes free space from %s to remove temporary data (%s and %s backup)...", ff_log(FC_NOTICE, 0, "%sclearing %.2f %sbytes free space from %s to remove temporary data (%s and %s backup)...",
sim_msg, pretty_len, pretty_label, label[FC_DEVICE], labe l[FC_PRIMARY_STORAGE], label[FC_DEVICE]); sim_msg, pretty_len, pretty_label, label[FC_DEVICE], labe l[FC_PRIMARY_STORAGE], label[FC_DEVICE]);
err = io->zero_primary_storage(); err = io->zero_primary_storage();
break; break;
default: default:
 End of changes. 43 change blocks. 
113 lines changed or deleted 71 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)