Commit d8cc8a6f authored by Simon Persson's avatar Simon Persson

Bug fix for detecting mounts on a directory

The fs plan executor did not detect when something got mounted on an existing directory. It only worked with udisk mounting since then a directory is created for use as mount point and kup detected the creation of the directory (and mount happened within 5 seconds after directory creation).
Now it also detect mounts on existing directories by monitoring /proc/mounts for changes, reads that file to find out if the watched directory turns up as a mount point.

Fixes #12.
parent c9641873
......@@ -31,6 +31,9 @@
#include <QDir>
#include <QFileInfo>
#include <QTimer>
#include <QTextStream>
#include <fcntl.h>
FSExecutor::FSExecutor(BackupPlan *pPlan, QObject *pParent)
:PlanExecutor(pPlan, pParent)
......@@ -38,6 +41,7 @@ FSExecutor::FSExecutor(BackupPlan *pPlan, QObject *pParent)
mDestinationPath = QDir::cleanPath(mPlan->mFilesystemDestinationPath.toLocalFile());
mDirWatch = new KDirWatch(this);
connect(mDirWatch, SIGNAL(deleted(QString)), SLOT(checkStatus()));
mMountWatcher.start();
}
void FSExecutor::checkStatus() {
......@@ -72,6 +76,7 @@ void FSExecutor::checkStatus() {
mDirWatch->removeDir(mWatchedParentDir);
} else { // start watching a parent
connect(mDirWatch, SIGNAL(dirty(QString)), SLOT(checkStatus()));
connect(&mMountWatcher, SIGNAL(mountsChanged()), SLOT(checkMountPoints()), Qt::QueuedConnection);
}
mWatchedParentDir = lExisting;
mDirWatch->addDir(mWatchedParentDir);
......@@ -83,6 +88,7 @@ void FSExecutor::checkStatus() {
// Destination exists... only watch for delete
if(!mWatchedParentDir.isEmpty()) {
disconnect(mDirWatch, SIGNAL(dirty(QString)), this, SLOT(checkStatus()));
disconnect(&mMountWatcher, SIGNAL(mountsChanged()), this, SLOT(checkMountPoints()));
mDirWatch->removeDir(mWatchedParentDir);
mWatchedParentDir.clear();
}
......@@ -138,3 +144,37 @@ void FSExecutor::slotBackupSizeDone(KJob *pJob) {
mPlan->writeConfig();
exitBackupRunningState(pJob->error() == 0);
}
void FSExecutor::checkMountPoints() {
QFile lMountsFile(QLatin1String("/proc/mounts"));
if(!lMountsFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
return;
}
// don't use atEnd() to detect when finished reading file, size of
// this special file is 0 but still returns data when read.
forever {
QByteArray lLine = lMountsFile.readLine();
if(lLine.isEmpty()) {
break;
}
QTextStream lTextStream(lLine);
QString lDevice, lMountPoint;
lTextStream >> lDevice >> lMountPoint;
if(lMountPoint == mWatchedParentDir) {
checkStatus();
}
}
}
void MountWatcher::run() {
int lMountsFd = open("/proc/mounts", O_RDONLY);
fd_set lFdSet;
forever {
FD_ZERO(&lFdSet);
FD_SET(lMountsFd, &lFdSet);
if(select(lMountsFd+1, NULL, NULL, &lFdSet, NULL) > 0) {
emit mountsChanged();
}
}
}
......@@ -23,6 +23,8 @@
#include "planexecutor.h"
#include <QThread>
class BackupPlan;
class KDirWatch;
......@@ -30,6 +32,19 @@ class KJob;
class QTimer;
// KDirWatch (well, inotify) does not detect when something gets mounted on a watched directory.
// work around this problem by monitoring the mounts of the system in a separate thread.
class MountWatcher: public QThread {
Q_OBJECT
signals:
void mountsChanged();
protected:
virtual void run();
};
// Plan executor that stores the backup to a path in the local
// filesystem, uses KDirWatch to monitor for when the folder
// becomes available/unavailable. Can be used for external
......@@ -49,10 +64,12 @@ protected slots:
virtual void startBackup();
void slotBackupDone(KJob *pJob);
void slotBackupSizeDone(KJob *pJob);
void checkMountPoints();
protected:
QString mWatchedParentDir;
KDirWatch *mDirWatch;
MountWatcher mMountWatcher;
};
#endif // FSEXECUTOR_H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment