From 602af83c322d31b62f5eb91605edafb8e98b4ca5 Mon Sep 17 00:00:00 2001 From: Rainer Toebbicke Date: Fri, 7 Sep 2007 05:05:49 +0000 Subject: [PATCH] STABLE14-namei-fsync-less-20070907 FIXES 30632 we call fsync() too much. call it less, and fsync in the background (cherry picked from commit dbbd59495bcda2a93d640f8cf5adf0b587f4591b) --- src/vol/ihandle.c | 77 +++++++++++++++++++++++++++++++++++++++++++ src/vol/ihandle.h | 3 +- src/vol/namei_ops.c | 2 ++ src/vol/vol-salvage.c | 9 +++++ 4 files changed, 90 insertions(+), 1 deletion(-) diff --git a/src/vol/ihandle.c b/src/vol/ihandle.c index d2650597a..2713bba8a 100644 --- a/src/vol/ihandle.c +++ b/src/vol/ihandle.c @@ -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(); + } +} /************************************************************************* diff --git a/src/vol/ihandle.h b/src/vol/ihandle.h index 2aee89da5..5b918f8a7 100644 --- a/src/vol/ihandle.h +++ b/src/vol/ihandle.h @@ -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) diff --git a/src/vol/namei_ops.c b/src/vol/namei_ops.c index 824a8a624..c818603b5 100644 --- a/src/vol/namei_ops.c +++ b/src/vol/namei_ops.c @@ -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); } diff --git a/src/vol/vol-salvage.c b/src/vol/vol-salvage.c index a0fd95608..b16596642 100644 --- a/src/vol/vol-salvage.c +++ b/src/vol/vol-salvage.c @@ -2875,12 +2875,16 @@ 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 sync(); /* this is slow, but hopefully rarely called. We don't have * 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); @@ -3345,6 +3349,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; -- 2.39.5