diff --git a/components/net/sf/briar/db/DatabaseComponentImpl.java b/components/net/sf/briar/db/DatabaseComponentImpl.java
index bc882aa4536e68cba5a775ca59cecdf20d3a1222..7ef8202db821f47106ff7df66f4128c27e4afe19 100644
--- a/components/net/sf/briar/db/DatabaseComponentImpl.java
+++ b/components/net/sf/briar/db/DatabaseComponentImpl.java
@@ -86,10 +86,8 @@ DatabaseCleaner.Callback {
 	private final List<DatabaseListener> listeners =
 		new ArrayList<DatabaseListener>(); // Locking: self
 	private final Object spaceLock = new Object();
-	private final Object writeLock = new Object();
 	private long bytesStoredSinceLastCheck = 0L; // Locking: spaceLock
 	private long timeOfLastCheck = 0L; // Locking: spaceLock
-	private volatile boolean writesAllowed = true;
 
 	@Inject
 	DatabaseComponentImpl(Database<T> db, DatabaseCleaner cleaner) {
@@ -162,7 +160,6 @@ DatabaseCleaner.Callback {
 
 	public void addLocalGroupMessage(Message m) throws DbException {
 		boolean added = false;
-		waitForPermissionToWrite();
 		contactLock.readLock().lock();
 		try {
 			messageLock.writeLock().lock();
@@ -201,23 +198,6 @@ DatabaseCleaner.Callback {
 		if(added) callListeners(Event.MESSAGES_ADDED);
 	}
 
-	/**
-	 * Blocks until messages are allowed to be stored in the database. The
-	 * storage of messages is not allowed while the amount of free storage
-	 * space available to the database is less than CRITICAL_FREE_SPACE.
-	 */
-	private void waitForPermissionToWrite() {
-		synchronized(writeLock) {
-			while(!writesAllowed) {
-				if(LOG.isLoggable(Level.FINE))
-					LOG.fine("Waiting for permission to write");
-				try {
-					writeLock.wait();
-				} catch(InterruptedException ignored) {}
-			}
-		}
-	}
-
 	/**
 	 * If the given message is already in the database, marks it as seen by the
 	 * sender and returns false. Otherwise stores the message, updates the
@@ -307,7 +287,6 @@ DatabaseCleaner.Callback {
 	public void addLocalPrivateMessage(Message m, ContactId c)
 	throws DbException {
 		boolean added = false;
-		waitForPermissionToWrite();
 		contactLock.readLock().lock();
 		try {
 			if(!containsContact(c)) throw new NoSuchContactException();
@@ -901,7 +880,6 @@ DatabaseCleaner.Callback {
 
 	public void receiveBatch(ContactId c, Batch b) throws DbException {
 		boolean anyAdded = false;
-		waitForPermissionToWrite();
 		contactLock.readLock().lock();
 		try {
 			if(!containsContact(c)) throw new NoSuchContactException();
@@ -1356,27 +1334,25 @@ DatabaseCleaner.Callback {
 	public void checkFreeSpaceAndClean() throws DbException {
 		long freeSpace = db.getFreeSpace();
 		while(freeSpace < MIN_FREE_SPACE) {
-			// If disk space is critical, disable the storage of new messages
-			if(freeSpace < CRITICAL_FREE_SPACE) {
-				if(LOG.isLoggable(Level.FINE)) LOG.fine("Critical cleanup");
-				writesAllowed = false;
-			} else {
-				if(LOG.isLoggable(Level.FINE)) LOG.fine("Normal cleanup");
+			boolean expired = expireMessages(BYTES_PER_SWEEP);
+			if(freeSpace < CRITICAL_FREE_SPACE && !expired) {
+				// FIXME: Work out what to do here - the amount of free space
+				// is critically low and there are no messages left to expire
+				System.err.println("Disk space is critical - shutting down");
+				System.exit(1);
 			}
-			expireMessages(BYTES_PER_SWEEP);
 			Thread.yield();
 			freeSpace = db.getFreeSpace();
-			// If disk space is no longer critical, re-enable writes
-			if(freeSpace >= CRITICAL_FREE_SPACE && !writesAllowed) {
-				writesAllowed = true;
-				synchronized(writeLock) {
-					writeLock.notifyAll();
-				}
-			}
 		}
 	}
 
-	private void expireMessages(int size) throws DbException {
+	/**
+	 * Removes the oldest messages from the database, with a total size less
+	 * than or equal to the given size, and returns true if any messages were
+	 * removed.
+	 */
+	private boolean expireMessages(int size) throws DbException {
+		Collection<MessageId> old;
 		contactLock.readLock().lock();
 		try {
 			messageLock.writeLock().lock();
@@ -1385,9 +1361,8 @@ DatabaseCleaner.Callback {
 				try {
 					T txn = db.startTransaction();
 					try {
-						for(MessageId m : db.getOldMessages(txn, size)) {
-							removeMessage(txn, m);
-						}
+						old = db.getOldMessages(txn, size);
+						for(MessageId m : old) removeMessage(txn, m);
 						db.commitTransaction(txn);
 					} catch(DbException e) {
 						db.abortTransaction(txn);
@@ -1402,6 +1377,7 @@ DatabaseCleaner.Callback {
 		} finally {
 			contactLock.readLock().unlock();
 		}
+		return old.isEmpty();
 	}
 
 	/**