summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2012-06-12 16:41:29 +0000
committerCarl Hetherington <carl@carlh.net>2012-06-12 16:41:29 +0000
commit92432f3e80d621816ac0b05484eb59fb9348ac34 (patch)
tree23c86f4359810044f0f5e82ca6277f6fa47eb14c /libs
parentd1d08e391059449977e7de1e858851ffd1afadc6 (diff)
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
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/session.h20
-rw-r--r--libs/ardour/session.cc10
-rw-r--r--libs/ardour/session_state.cc47
-rw-r--r--libs/ardour/wscript1
4 files changed, 63 insertions, 15 deletions
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<framecnt_t> 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<space_and_path> session_dirs;
std::vector<space_and_path>::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<framecnt_t>
Session::available_capture_duration ()
{
+ if (_total_free_4k_blocks_uncertain) {
+ return boost::optional<framecnt_t> ();
+ }
+
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 <sys/mount.h>
#endif
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+
#include <glib.h>
#include <glibmm.h>
@@ -2079,23 +2083,48 @@ Session::save_template (string template_name)
void
Session::refresh_disk_space ()
{
-#if HAVE_SYS_VFS_H
- struct statfs statfsbuf;
- vector<space_and_path>::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<space_and_path>::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')