[Raw Msg Headers][Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[ZMailer] Broken mailbox files on NFS, linux 2.6



Hi All!

As known, NFS client at Linux 2.6 works strange.
If you have filesystem quota and try to write data size exceeds quota, you break yours data.
Simple test_nfswrite.c program (gcc test_nfswrite.c -o test_nfswrite):
---
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
int main(int arc, char * argv[]) {
    int fd;
    int rc;
    int i;
    int size = 1024;
    char *buf;
    int it;

    it = atoi(argv[1]);

    buf = (char*)malloc(size * sizeof(char));
    memset(buf, 'a', size - 1);
    buf[size - 1] = '\0';

/* Open test file on "quota on" file system */
    fd = open("/mount/m7/tmp/test", O_RDWR);

    for(i = 0; i < it; i++) {
    /* Write 1024 bytes blocks */1
        rc = write(fd, buf, strlen(buf));
        printf("write: %d, errno = %s\n", rc, strerror(errno));
    }
    rc = fsync(fd);
    printf("fsync: %d, errno = %s\n", rc, strerror(errno));
    rc = fdatasync(fd);
    printf("fdatasync: %d, errno = %s\n", rc, strerror(errno));
    rc = close(fd);
    printf("close: %d\n", rc);

    free(buf);
    return 0;
}
---
Run: ./test_nfswrite 120
(write 120*1024 bytes block, set more blocks for write overquota data)

On 2.4 you receive error on write stage then data size exceeds quota.
On 2.6 it always says OK. But you receive broken "test" file.

If you change:
---
-   fd = open("/mount/m7/tmp/test", O_RDWR);
+   fd = open("/mount/m7/tmp/test", O_RDWR|O_SYNC);
---
everything will work well on 2.6 - error on write stage.

Here is patch for last Zmailer (many thanx to Mike <fandorin(at)rol.ru>):

--- ./zmailer.orig/transports/mailbox/mailbox.c 2006-06-26 20:28:03.000000000 +0400
+++ ./zmailer/transports/mailbox/mailbox.c      2009-06-22 16:49:18.000000000 +0400
@@ -1753,7 +1753,8 @@
                  "To open a file with euid=%d egid=%d ismbox=%d file='%s'\n",
                  (int)geteuid(), (int)getegid(), ismbox, file);

-       fdmail = open(file, O_RDWR|O_APPEND);
+/* koc */
+       fdmail = open(file, O_RDWR|O_APPEND|O_SYNC);

        if (fdmail < 0) {
          char fmtbuf[512];
@@ -1997,6 +1998,11 @@
       int rc = write(sffileno(sfp), p, len);
       int e  = errno;

+/* koc */
+      if ((rc < 0) && (fsync(sffileno(sfp)) < 0)) {
+        if (errno == EDQUOT) e  = errno;
+      }
+
 if (verboselog)
   fprintf(verboselog, " mbox_sfwrite(ptr, len=%d) rc=%d errno=%d\n",
          (int)len, rc, e);


=koc

--
To unsubscribe from this list: send the line "unsubscribe zmailer" in
the body of a message to majordomo@nic.funet.fi