From: Rainer Toebbicke Date: Sun, 15 Mar 2009 18:50:10 +0000 (+0000) Subject: DEVEL15-viced-copyonwrite-optimization-20090315 X-Git-Tag: openafs-devel-1_5_58~111 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=d84bb72e26dc9b0325a9212e440498e4e64bfcb6;p=packages%2Fo%2Fopenafs.git DEVEL15-viced-copyonwrite-optimization-20090315 LICENSE IPL10 FIXES 124397 optimize CopyOnWrite to avoid rewriting data if possible (cherry picked from commit 0c39a855a2da7b3e82970c65f835eed38b650215) --- diff --git a/src/viced/afsfileprocs.c b/src/viced/afsfileprocs.c index f48c01b98..e4e67e85b 100644 --- a/src/viced/afsfileprocs.c +++ b/src/viced/afsfileprocs.c @@ -198,6 +198,8 @@ afs_int32 BlocksSpare = 1024; /* allow 1 MB overruns */ afs_int32 PctSpare; extern afs_int32 implicitAdminRights; extern afs_int32 readonlyServer; +extern int CopyOnWrite_calls, CopyOnWrite_off0, CopyOnWrite_size0; +extern afs_fsize_t CopyOnWrite_maxsize; /* * Externals used by the xstat code. @@ -1092,8 +1094,9 @@ RXStore_AccessList(Vnode * targetptr, struct AFSOpaque *AccessList) * disk.inodeNumber and cloned) */ #define COPYBUFFSIZE 8192 +#define MAXFSIZE (~(afs_fsize_t) 0) static int -CopyOnWrite(Vnode * targetptr, Volume * volptr) +CopyOnWrite(Vnode * targetptr, Volume * volptr, afs_fsize_t off, afs_fsize_t len) { Inode ino, nearInode; int rdlen; @@ -1110,6 +1113,13 @@ CopyOnWrite(Vnode * targetptr, Volume * volptr) DFlush(); /* just in case? */ VN_GET_LEN(size, targetptr); + if (size > off) + size -= off; + else + size = 0; + if (size > len) + size = len; + buff = (char *)malloc(COPYBUFFSIZE); if (buff == NULL) { return EIO; @@ -1153,6 +1163,8 @@ CopyOnWrite(Vnode * targetptr, Volume * volptr) newFdP = IH_OPEN(newH); assert(newFdP != NULL); + FDH_SEEK(targFdP, off, SEEK_SET); + FDH_SEEK(newFdP, off, SEEK_SET); while (size > 0) { if (size > COPYBUFFSIZE) { /* more than a buffer */ length = COPYBUFFSIZE; @@ -1234,6 +1246,41 @@ CopyOnWrite(Vnode * targetptr, Volume * volptr) return 0; /* success */ } /*CopyOnWrite */ +static int +CopyOnWrite2(FdHandle_t *targFdP, FdHandle_t *newFdP, afs_fsize_t off, afs_fsize_t size) { + char *buff = (char *)malloc(COPYBUFFSIZE); + register int length; + int rdlen; + int wrlen; + int rc; + + FDH_SEEK(targFdP, off, SEEK_SET); + FDH_SEEK(newFdP, off, SEEK_SET); + + while (size > 0) { + if (size > COPYBUFFSIZE) { /* more than a buffer */ + length = COPYBUFFSIZE; + size -= COPYBUFFSIZE; + } else { + length = (int)size; + size = 0; + } + rdlen = FDH_READ(targFdP, buff, length); + if (rdlen == length) + wrlen = FDH_WRITE(newFdP, buff, length); + else + wrlen = 0; + + if ((rdlen != length) || (wrlen != length)) { + /* no error recovery, at the worst we'll have a "hole" in the file */ + rc = 1; + break; + } + } + free(buff); + return rc; +} + /* * Common code to handle with removing the Name (file when it's called from @@ -1254,7 +1301,7 @@ DeleteTarget(Vnode * parentptr, Volume * volptr, Vnode ** targetptr, return (EINVAL); if (parentptr->disk.cloned) { ViceLog(25, ("DeleteTarget : CopyOnWrite called\n")); - if ((errorCode = CopyOnWrite(parentptr, volptr))) { + if ((errorCode = CopyOnWrite(parentptr, volptr, 0, MAXFSIZE))) { ViceLog(20, ("DeleteTarget %s: CopyOnWrite failed %d\n", Name, errorCode)); @@ -1698,7 +1745,7 @@ Alloc_NewVnode(Vnode * parentptr, DirHandle * dir, Volume * volptr, if (parentptr->disk.cloned) { ViceLog(25, ("Alloc_NewVnode : CopyOnWrite called\n")); - if ((errorCode = CopyOnWrite(parentptr, volptr))) { /* disk full */ + if ((errorCode = CopyOnWrite(parentptr, volptr, 0, MAXFSIZE))) { /* disk full */ ViceLog(25, ("Alloc_NewVnode : CopyOnWrite failed\n")); /* delete the vnode previously allocated */ (*targetptr)->delete = 1; @@ -3866,13 +3913,13 @@ SAFSS_Rename(struct rx_call *acall, struct AFSFid *OldDirFid, char *OldName, */ if (oldvptr->disk.cloned) { ViceLog(25, ("Rename : calling CopyOnWrite on old dir\n")); - if ((errorCode = CopyOnWrite(oldvptr, volptr))) + if ((errorCode = CopyOnWrite(oldvptr, volptr, 0, MAXFSIZE))) goto Bad_Rename; } SetDirHandle(&olddir, oldvptr); if (newvptr->disk.cloned) { ViceLog(25, ("Rename : calling CopyOnWrite on new dir\n")); - if ((errorCode = CopyOnWrite(newvptr, volptr))) + if ((errorCode = CopyOnWrite(newvptr, volptr, 0, MAXFSIZE))) goto Bad_Rename; } @@ -4022,7 +4069,7 @@ SAFSS_Rename(struct rx_call *acall, struct AFSFid *OldDirFid, char *OldName, */ if ((fileptr->disk.type == vDirectory) && (fileptr->disk.cloned)) { ViceLog(25, ("Rename : calling CopyOnWrite on target dir\n")); - if ((errorCode = CopyOnWrite(fileptr, volptr))) + if ((errorCode = CopyOnWrite(fileptr, volptr, 0, MAXFSIZE))) goto Bad_Rename; } @@ -4534,7 +4581,7 @@ SAFSS_Link(struct rx_call *acall, struct AFSFid *DirFid, char *Name, } if (parentptr->disk.cloned) { ViceLog(25, ("Link : calling CopyOnWrite on target dir\n")); - if ((errorCode = CopyOnWrite(parentptr, volptr))) + if ((errorCode = CopyOnWrite(parentptr, volptr, 0, MAXFSIZE))) goto Bad_Link; /* disk full error */ } @@ -7156,7 +7203,8 @@ StoreData_RXStyle(Volume * volptr, Vnode * targetptr, struct AFSFid * Fid, afs_fsize_t NewLength; /* size after this store completes */ afs_sfsize_t adjustSize; /* bytes to call VAdjust... with */ int linkCount = 0; /* link count on inode */ - FdHandle_t *fdP; + afs_fsize_t CoW_off = 0, CoW_len = 0; + FdHandle_t *fdP, *origfdP = NULL; struct in_addr logHostAddr; /* host ip holder for inet_ntoa */ #if FS_STATS_DETAILED @@ -7215,20 +7263,32 @@ StoreData_RXStyle(Volume * volptr, Vnode * targetptr, struct AFSFid * Fid, * mechanisms (i.e. copy on write overhead.) Also the right size * of the disk will be recorded... */ - FDH_CLOSE(fdP); + origfdP = fdP; VN_GET_LEN(size, targetptr); volptr->partition->flags &= ~PART_DONTUPDATE; VSetPartitionDiskUsage(volptr->partition); volptr->partition->flags |= PART_DONTUPDATE; if ((errorCode = VDiskUsage(volptr, nBlocks(size)))) { volptr->partition->flags &= ~PART_DONTUPDATE; + FDH_CLOSE(origfdP); return (errorCode); } - ViceLog(25, ("StoreData : calling CopyOnWrite on target dir\n")); - if ((errorCode = CopyOnWrite(targetptr, volptr))) { + if (Pos == 0) + CoW_off = Length; /* only copy remaining parts of file */ + if (Length <= FileLength) + CoW_len = FileLength - Length; + CopyOnWrite_calls++; + if (CoW_len == 0) CopyOnWrite_size0++; + if (CoW_off == 0) CopyOnWrite_off0++; + if (CoW_len > CopyOnWrite_maxsize) CopyOnWrite_maxsize = CoW_len; + + ViceLog(1, ("StoreData : calling CopyOnWrite on vnode %lu.%lu (%s) off 0x%llx size 0x%llx\n", + V_id(volptr), targetptr->vnodeNumber, V_name(volptr), CoW_off, CoW_len)); + if ((errorCode = CopyOnWrite(targetptr, volptr, CoW_off, CoW_len))) { ViceLog(25, ("StoreData : CopyOnWrite failed\n")); volptr->partition->flags &= ~PART_DONTUPDATE; + FDH_CLOSE(origfdP); return (errorCode); } volptr->partition->flags &= ~PART_DONTUPDATE; @@ -7237,6 +7297,7 @@ StoreData_RXStyle(Volume * volptr, Vnode * targetptr, struct AFSFid * Fid, if (fdP == NULL) { ViceLog(25, ("StoreData : Reopen after CopyOnWrite failed\n")); + FDH_CLOSE(origfdP); return ENOENT; } } @@ -7268,6 +7329,7 @@ StoreData_RXStyle(Volume * volptr, Vnode * targetptr, struct AFSFid * Fid, AdjustDiskUsage(volptr, adjustSize, adjustSize - SpareComp(volptr)))) { FDH_CLOSE(fdP); + if (origfdP) FDH_CLOSE(origfdP); return (errorCode); } @@ -7363,6 +7425,9 @@ StoreData_RXStyle(Volume * volptr, Vnode * targetptr, struct AFSFid * Fid, * need to update the target vnode. */ targetptr->changed_newTime = 1; + if (origfdP && (bytesTransfered < Length)) /* Need to "finish" CopyOnWrite still */ + CopyOnWrite2(origfdP, fdP, bytesTransfered, Length - bytesTransfered); + if (origfdP) FDH_CLOSE(origfdP); FDH_CLOSE(fdP); /* set disk usage to be correct */ VAdjustDiskUsage(&errorCode, volptr, @@ -7370,6 +7435,7 @@ StoreData_RXStyle(Volume * volptr, Vnode * targetptr, struct AFSFid * Fid, nBlocks(NewLength)), 0); return errorCode; } + if (origfdP) FDH_CLOSE(origfdP); FDH_CLOSE(fdP); FT_GetTimeOfDay(&StopTime, 0); diff --git a/src/viced/viced.c b/src/viced/viced.c index a201e8f00..ceffdbc58 100644 --- a/src/viced/viced.c +++ b/src/viced/viced.c @@ -698,6 +698,8 @@ ClearXStatValues() } /*ClearXStatValues */ +int CopyOnWrite_calls = 0, CopyOnWrite_off0 = 0, CopyOnWrite_size0 = 0; +afs_fsize_t CopyOnWrite_maxsize = 0; static void PrintCounters() @@ -741,6 +743,9 @@ PrintCounters() ViceLog(0, ("There are %d workstations, %d are active (req in < 15 mins), %d marked \"down\"\n", workstations, activeworkstations, delworkstations)); + ViceLog(0, ("CopyOnWrite: calls %d off0 %d size0 %d maxsize 0x%llx\n", + CopyOnWrite_calls, CopyOnWrite_off0, CopyOnWrite_size0, CopyOnWrite_maxsize)); + Statistics = 0; } /*PrintCounters */