namei-fsync-less-20070907
authorRainer Toebbicke <rtb@pclella.cern.ch>
Fri, 7 Sep 2007 05:02:09 +0000 (05:02 +0000)
committerDerrick Brashear <shadow@dementia.org>
Fri, 7 Sep 2007 05:02:09 +0000 (05:02 +0000)
FIXES 30632

we call fsync() too much. call it less, and fsync in the background

src/vol/ihandle.c
src/vol/ihandle.h
src/vol/namei_ops.c
src/vol/vol-salvage.c

index d265059..2713bba 100644 (file)
@@ -154,6 +154,24 @@ ih_Initialize(void)
     }
 #endif
     fdCacheSize = MIN(fdMaxCacheSize, FD_DEFAULT_CACHESIZE);
+
+    {
+       void *ih_sync_thread();
+#ifdef AFS_PTHREAD_ENV
+       pthread_t syncer;
+       pthread_attr_t tattr;
+
+       pthread_attr_init(&tattr);
+       pthread_attr_setdetachstate(&tattr,PTHREAD_CREATE_DETACHED);
+
+       pthread_create(&syncer, &tattr, ih_sync_thread, NULL);
+#else /* AFS_PTHREAD_ENV */
+       PROCESS syncer;
+       LWP_CreateProcess(ih_sync_thread, 16*1024, LWP_MAX_PRIORITY - 2,
+           NULL, "ih_syncer", &syncer);
+#endif /* AFS_PTHREAD_ENV */
+    }
+
 }
 
 /* Make the file descriptor cache as big as possible. Don't this call
@@ -840,6 +858,65 @@ ih_condsync(IHandle_t * ihP)
     return code;
 }
 
+void
+ih_sync_all() {
+    int ihash;
+
+    IH_LOCK;
+    for (ihash = 0; ihash < I_HANDLE_HASH_SIZE; ihash++) {
+       IHandle_t *ihP, *ihPnext;
+
+       ihP = ihashTable[ihash].ihash_head;
+       if (ihP)
+           ihP->ih_refcnt++;   /* must not disappear over unlock */
+       for (; ihP; ihP = ihPnext) {
+           
+           if (ihP->ih_synced) {
+               FdHandle_t *fdP;
+
+               ihP->ih_synced = 0;
+               IH_UNLOCK;
+
+               fdP = IH_OPEN(ihP);
+               if (fdP) OS_SYNC(fdP->fd_fd);
+               FDH_CLOSE(fdP);
+
+               IH_LOCK;
+           }
+
+           /* when decrementing the refcount, the ihandle might disappear
+              and we might not even be able to proceed to the next one.
+              Hence the gymnastics putting a hold on the next one already */
+           ihPnext = ihP->ih_next;
+           if (ihPnext) ihPnext->ih_refcnt++;
+
+           if (ihP->ih_refcnt > 1) {
+               ihP->ih_refcnt--;
+           } else {
+               IH_UNLOCK;
+               ih_release(ihP);
+               IH_LOCK;
+           }
+
+       }
+    }
+    IH_UNLOCK;
+}
+
+void *
+ih_sync_thread() {
+    while(1) {
+
+#ifdef AFS_PTHREAD_ENV
+       sleep(10);
+#else /* AFS_PTHREAD_ENV */
+       IOMGR_Sleep(60);
+#endif /* AFS_PTHREAD_ENV */
+
+       sync();
+       ih_sync_all();
+    }
+}
 
 
 /*************************************************************************
index 2aee89d..5b918f8 100644 (file)
@@ -211,6 +211,7 @@ typedef struct IHandle_s {
     int ih_vid;                        /* Parent volume id. */
     int ih_dev;                        /* device id. */
     int ih_flags;              /* Flags */
+    int ih_synced;             /* should be synced next time */
     Inode ih_ino;              /* Inode number */
     int ih_refcnt;             /* reference count */
     struct FdHandle_s *ih_fdhead;      /* List of open file desciptors */
@@ -466,7 +467,7 @@ extern afs_sfsize_t ih_size(int fd);
 #define FDH_WRITE(H, B, S) OS_WRITE((H)->fd_fd, B, S)
 #define FDH_SEEK(H, O, F) OS_SEEK((H)->fd_fd, O, F)
 
-#define FDH_SYNC(H) OS_SYNC((H)->fd_fd)
+#define FDH_SYNC(H) ((H->fd_ih!=NULL) ? ( H->fd_ih->ih_synced = 1) - 1 : 1)
 #define FDH_TRUNC(H, L) OS_TRUNC((H)->fd_fd, L)
 #define FDH_SIZE(H) OS_SIZE((H)->fd_fd)
 
index 824a8a6..c818603 100644 (file)
@@ -604,6 +604,8 @@ namei_icreate(IHandle_t * lh, char *part, int p1, int p2, int p3, int p4)
 
     if (p2 == -1 && p3 == VI_LINKTABLE) {
        /* hack at tmp to setup for set link count call. */
+       memset((void *)&tfd, 0, sizeof(FdHandle_t));    /* minimalistic still, but a little cleaner */
+       tfd.fd_ih = &tmp;
        tfd.fd_fd = fd;
        code = namei_SetLinkCount(&tfd, (Inode) 0, 1, 0);
     }
index 76a5838..e5158e9 100644 (file)
@@ -2358,6 +2358,7 @@ CopyAndSalvage(register struct DirSummary *dir)
                  vnodeIndexOffset(vcp, dir->vnodeNumber), (char *)&vnode,
                  sizeof(vnode));
     assert(lcode == sizeof(vnode));
+#if 0
 #ifdef AFS_NT40_ENV
     nt_sync(fileSysDevice);
 #else
@@ -2365,6 +2366,9 @@ CopyAndSalvage(register struct DirSummary *dir)
                                 * an open FD on the file itself to fsync.
                                 */
 #endif
+#else
+    vnodeInfo[vLarge].handle->ih_synced = 1;
+#endif
     code = IH_DEC(dir->ds_linkH, oldinode, dir->rwVid);
     assert(code == 0);
     dir->dirHandle = newdir;
@@ -2828,6 +2832,11 @@ SalvageVolume(register struct InodeSummary *rwIsp, IHandle_t * alinkH)
        SalvageDir(volHeader.name, vid, dirVnodeInfo, alinkH, i, &rootdir,
                   &rootdirfound);
     }
+#ifdef AFS_NT40_ENV
+    nt_sync(fileSysDevice);
+#else
+    sync();                            /* This used to be done lower level, for every dir */
+#endif
     if (Showmode) {
        IH_RELEASE(h);
        return 0;