Subject: Re: Retrying after disk error

From: Mark Crispin <[email-masked]>
Date: Tue, 11 Nov 1997 18:02:48 -0800 (PST)

OK, thanks to information from Oohira Shinya, I understand the problem.

First, a clarification.  This problem is NOT a problem in imapd, nor is it a
problem in c-client's local file drivers.  It is specifically an ipop[23]d
problem.

The problem occurs only when the user opens a mailbox using POP, is extremely
near his disk quota, and is using a "keep mail on the server" client.  The
user is trying to log out.  This entails an update to the mailbox, including
saving the unique identifier and status for all messages.  This could entail
the mailbox needing to grow, particularly for new messages (it must create a
Status:, X-Status:, and X-UID: header line).

The server determines how big the mailbox needs to be, and before doing any
rewrite of the mailbox it expands the mailbox to that size by appending nulls
to the end of the mailbox.  It does this so that in the event of a failure, it
can back out without losing data.

In IMAP, the client is given an untagged BYE with "Aborting due to disk error:
Disk quota exceeded" message, then it quits.  imapd has failed to do what it
promised to do, but at least it reported to the user that it failed and why.

However, in POP, there is no way to report that the server has failed to
perform as promised.  This leaves a choice; it can give up silently (losing
state and UIDs!!!), or it can wait and retry.  The code currently does the
latter; it blocks for 5 seconds and tries again.

If you want the code to do the former, you need to change mm_diskerror() in
ipop3d.c to return T.  You probably want code something like:

long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
{
  char tmp[MAILTMPLEN];
  if (serious) {
    syslog (LOG_ALERT,
	    "Retry after disk error user=%.80s host=%.80s mbx=%.80s: %.80s",
	    user,tcp_clienthost (tmp),
	    (stream && stream->mailbox) ? stream->mailbox : "???",
	    strerror (errcode));
    sleep (5);			/* can't do much better than this! */
    return NIL;
  }
  syslog (LOG_ALERT,
	  "Disk error user=%.80s host=%.80s mbx=%.80s: %.80s",
	  user,tcp_clienthost (tmp),
	  (stream && stream->mailbox) ? stream->mailbox : "???",
	  strerror (errcode));
  return T;
}

Note that even if you return T it will retry when "serious" is non-NIL, since
irrecoverable damage was done to the mailbox otherwise.

There is no good way to win; POP can not indicate failures to the client.
Either you let it retry and have a system manager fix this, or you let it fail
and lose state.

The only way to work around the problem at the client end is to delete
messages on the server.

*Begin Soapbox*

It is better not to use disk quotas at all.  Disk space costs less than 5
cents a megabyte.  Far more money is wasted in staff salaries dealing with
problems caused by disk quotas that cause software to fail irrecoverably.  I
can make the software not trash mailboxes due to disk quota problems, but
there is no way that I can make things work if you provide such hard limits
that a simple update can't work.

If you must use disk quotas, you should consider a quota system which stops
mail delivery at a "soft" limit but otherwise permits file writes.  Even in
the bad old days when disk space was expensive, there was still a recognition
of a need to be able to exceed the quota in a small way.

*End Soapbox*