From 92432f3e80d621816ac0b05484eb59fb9348ac34 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 12 Jun 2012 16:41:29 +0000 Subject: Handle failure of statfs to return available disc space on Samba shares mounted via GVFS, reporting available space as unknown in this case (#4657). git-svn-id: svn://localhost/ardour2/branches/3.0@12674 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/session.h | 20 ++++++++++++++----- libs/ardour/session.cc | 10 +++++++++- libs/ardour/session_state.cc | 47 +++++++++++++++++++++++++++++++++++--------- libs/ardour/wscript | 1 + 4 files changed, 63 insertions(+), 15 deletions(-) (limited to 'libs') diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 9dd19eb2a1..f7f8516ef3 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -669,7 +669,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi /* s/w "RAID" management */ - framecnt_t available_capture_duration(); + boost::optional available_capture_duration(); /* I/O bundles */ @@ -1329,16 +1329,21 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi /* S/W RAID */ struct space_and_path { - uint32_t blocks; /* 4kB blocks */ + uint32_t blocks; ///< 4kB blocks + bool blocks_unknown; ///< true if blocks is unknown std::string path; - space_and_path() { - blocks = 0; - } + space_and_path () + : blocks (0) + , blocks_unknown (true) + {} }; struct space_and_path_ascending_cmp { bool operator() (space_and_path a, space_and_path b) { + if (a.blocks_unknown != b.blocks_unknown) { + return !a.blocks_unknown; + } return a.blocks > b.blocks; } }; @@ -1348,6 +1353,11 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi std::vector session_dirs; std::vector::iterator last_rr_session_dir; uint32_t _total_free_4k_blocks; + /** If this is true, _total_free_4k_blocks is not definite, + as one or more of the session directories' filesystems + could not report free space. + */ + bool _total_free_4k_blocks_uncertain; Glib::Mutex space_lock; bool no_questions_about_missing_files; diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 9267832cb1..f78a26cc05 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -143,6 +143,7 @@ Session::Session (AudioEngine &eng, , _all_route_group (new RouteGroup (*this, "all")) , routes (new RouteList) , _total_free_4k_blocks (0) + , _total_free_4k_blocks_uncertain (false) , _bundles (new BundleList) , _bundle_xml_node (0) , _current_trans (0) @@ -3501,9 +3502,16 @@ Session::graph_reordered () } } -framecnt_t +/** @return Number of frames that there is disk space available to write, + * if known. + */ +boost::optional Session::available_capture_duration () { + if (_total_free_4k_blocks_uncertain) { + return boost::optional (); + } + float sample_bytes_on_disk = 4.0; // keep gcc happy switch (config.get_native_file_data_format()) { diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index e729a7b00d..30f8571c01 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -46,6 +46,10 @@ #include #endif +#ifdef HAVE_SYS_STATVFS_H +#include +#endif + #include #include @@ -2079,23 +2083,48 @@ Session::save_template (string template_name) void Session::refresh_disk_space () { -#if HAVE_SYS_VFS_H - struct statfs statfsbuf; - vector::iterator i; +#if HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H + Glib::Mutex::Lock lm (space_lock); - double scale; /* get freespace on every FS that is part of the session path */ _total_free_4k_blocks = 0; + _total_free_4k_blocks_uncertain = false; - for (i = session_dirs.begin(); i != session_dirs.end(); ++i) { - statfs ((*i).path.c_str(), &statfsbuf); + for (vector::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) { + + struct statfs statfsbuf; + statfs (i->path.c_str(), &statfsbuf); - scale = statfsbuf.f_bsize/4096.0; + double const scale = statfsbuf.f_bsize / 4096.0; - (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale); - _total_free_4k_blocks += (*i).blocks; + /* See if this filesystem is read-only */ + struct statvfs statvfsbuf; + statvfs (i->path.c_str(), &statvfsbuf); + + /* f_bavail can be 0 if it is undefined for whatever + filesystem we are looking at; Samba shares mounted + via GVFS are an example of this. + */ + if (statfsbuf.f_bavail == 0) { + /* block count unknown */ + i->blocks = 0; + i->blocks_unknown = true; + } else if (statvfsbuf.f_flag & ST_RDONLY) { + /* read-only filesystem */ + i->blocks = 0; + i->blocks_unknown = false; + } else { + /* read/write filesystem with known space */ + i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale); + i->blocks_unknown = false; + } + + _total_free_4k_blocks += i->blocks; + if (i->blocks_unknown) { + _total_free_4k_blocks_uncertain = true; + } } #endif } diff --git a/libs/ardour/wscript b/libs/ardour/wscript index c0fcec8d29..25a2cb6d92 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -289,6 +289,7 @@ def configure(conf): conf.define('CURRENT_SESSION_FILE_VERSION', CURRENT_SESSION_FILE_VERSION) conf.check(header_name='sys/vfs.h', define_name='HAVE_SYS_VFS_H',mandatory=False) + conf.check(header_name='sys/statvfs.h', define_name='HAVE_SYS_STATVFS_H',mandatory=False) conf.check(header_name='jack/session.h', uselib = [ 'JACK' ], define_name='HAVE_JACK_SESSION') -- cgit v1.2.3