From 1f3990e5eafb6bd9dfdae28ce4fea5b8e5cff79e Mon Sep 17 00:00:00 2001 From: Nathan Neulinger Date: Thu, 19 Jun 2003 17:06:58 +0000 Subject: [PATCH] vos-getsize-20030619 FIXES 1574 ported basically verbatim from work by ilya@ccmr.cornell.edu and mitch@ccmr.cornell.edu. add estimator of dump size support to vos/volserver --- src/volser/dumpstuff.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++ src/volser/volint.xg | 12 +++ src/volser/volprocs.c | 27 ++++++ src/volser/vos.c | 82 ++++++++++++++++++ src/volser/vsprocs.c | 39 +++++++++ 5 files changed, 379 insertions(+) diff --git a/src/volser/dumpstuff.c b/src/volser/dumpstuff.c index ad98ad7..c239315 100644 --- a/src/volser/dumpstuff.c +++ b/src/volser/dumpstuff.c @@ -92,6 +92,17 @@ static int ReadVnodes(register struct iod *iodp, Volume *vp, static bit32 volser_WriteFile(int vn, struct iod *iodp, FdHandle_t *handleP, Error *status); +static int SizeDumpDumpHeader(register struct iod *iodp, register Volume *vp, + afs_int32 fromtime, register struct volintSize *size); +static int SizeDumpPartial(register struct iod *iodp, register Volume *vp, + afs_int32 fromtime, int dumpAllDirs, + register struct volintSize *size); +static int SizeDumpVnodeIndex(register struct iod *iodp, Volume *vp, + VnodeClass class, afs_int32 fromtime, int forcedump, + register struct volintSize *size); +static int SizeDumpVnode(register struct iod *iodp, struct VnodeDiskObject *v, + int volid, int vnodeNumber, int dumpEverything, + register struct volintSize *size); static void iod_Init(register struct iod *iodp, register struct rx_call *call) { @@ -1154,3 +1165,211 @@ static int ReadDumpHeader(register struct iod *iodp, struct DumpHeader *hp) iod_ungetc(iodp, tag); return 1; } + + +/* ----- Below are the calls that calculate dump size ----- */ + +static int SizeDumpVolumeHeader(register struct iod *iodp, register Volume *vp, register struct volintSize *v_size) +{ + int code = 0; + static char nullString[1] = ""; /*The ``contents'' of motd*/ + +/* if (!code) code = DumpTag(iodp, D_VOLUMEHEADER); */ + v_size->dump_size += 1; +/* if (!code) {code = DumpInt32(iodp, 'i',V_id(vp));} */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 'v',V_stamp(vp).version); */ + v_size->dump_size += 5; +/* if (!code) code = DumpString(iodp, 'n',V_name(vp)); */ + v_size->dump_size += (2 + strlen(V_name(vp))); +/* if (!code) code = DumpBool(iodp, 's',V_inService(vp)); */ + v_size->dump_size += 2; +/* if (!code) code = DumpBool(iodp, 'b',V_blessed(vp)); */ + v_size->dump_size += 2; +/* if (!code) code = DumpInt32(iodp, 'u',V_uniquifier(vp)); */ + v_size->dump_size += 5; +/* if (!code) code = DumpByte(iodp, 't',(byte)V_type(vp)); */ + v_size->dump_size += 2; +/* if (!code){ code = DumpInt32(iodp, 'p',V_parentId(vp));} */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 'c',V_cloneId(vp)); */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 'q',V_maxquota(vp)); */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 'm',V_minquota(vp)); */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 'd',V_diskused(vp)); */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 'f',V_filecount(vp)); */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 'a', V_accountNumber(vp)); */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 'o', V_owner(vp)); */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 'C',V_creationDate(vp)); /\* Rw volume creation date *\/ */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 'A',V_accessDate(vp)); */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 'U',V_updateDate(vp)); */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 'E',V_expirationDate(vp)); */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 'B',V_backupDate(vp)); /\* Rw volume backup clone date *\/ */ + v_size->dump_size += 5; +/* if (!code) code = DumpString(iodp, 'O',V_offlineMessage(vp)); */ + v_size->dump_size += (2 + strlen(V_offlineMessage(vp))); +/* /\* */ +/* * We do NOT dump the detailed volume statistics residing in the old */ +/* * motd field, since we cannot tell from the info in a dump whether */ +/* * statistics data has been put there. Instead, we dump a null string, */ +/* * just as if that was what the motd contained. */ +/* *\/ */ +/* if (!code) code = DumpString(iodp, 'M', nullString); */ + v_size->dump_size += (2 + strlen(nullString)); +/* if (!code) code = DumpArrayInt32(iodp, 'W', (afs_uint32 *)V_weekUse(vp), sizeof(V_weekUse(vp))/sizeof(V_weekUse(vp)[0])); */ + v_size->dump_size += (3 + 4*(sizeof(V_weekUse(vp))/sizeof(V_weekUse(vp)[0]))); +/* if (!code) code = DumpInt32(iodp, 'D', V_dayUseDate(vp)); */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 'Z', V_dayUse(vp)); */ + v_size->dump_size += 5; + return code; +} + +static int SizeDumpEnd(register struct iod *iodp, register struct volintSize *v_size) +{ + int code = 0; + v_size->dump_size += 5; + return code; +} + +int SizeDumpVolume(register struct rx_call *call, register Volume *vp, afs_int32 fromtime, + int dumpAllDirs, register struct volintSize *v_size) +{ + struct iod iod; + int code = 0; + register struct iod *iodp = (struct iod *)0; +// iod_Init(iodp, call); + + if (!code) code = SizeDumpDumpHeader(iodp, vp, fromtime, v_size); + if (!code) code = SizeDumpPartial(iodp, vp, fromtime, dumpAllDirs, v_size); + if (!code) code = SizeDumpEnd(iodp, v_size); + + return code; +} + +static int SizeDumpDumpHeader(register struct iod *iodp, register Volume *vp, afs_int32 fromtime, + register struct volintSize *v_size) +{ + int code = 0; + int UseLatestReadOnlyClone = 1; + afs_int32 dumpTimes[2]; +// iodp->device = vp->device; +// iodp->parentId = V_parentId(vp); +// iodp->dumpPartition = vp->partition; + + v_size->dump_size = 0; /* initialize the size */ +/* if (!code) code = DumpDouble(iodp, D_DUMPHEADER, DUMPBEGINMAGIC, DUMPVERSION); */ + v_size->dump_size += 9; +/* if (!code) code = DumpInt32(iodp, 'v', UseLatestReadOnlyClone? V_id(vp): V_parentId(vp)); */ + v_size->dump_size += 5; +/* if (!code) code = DumpString(iodp, 'n',V_name(vp)); */ + v_size->dump_size += (2 + strlen(V_name(vp))); +/* dumpTimes[0] = fromtime; */ +/* dumpTimes[1] = V_backupDate(vp); /\* Until the time the clone was made *\/ */ +/* if (!code) code = DumpArrayInt32(iodp, 't', (afs_uint32 *)dumpTimes, 2); */ + v_size->dump_size += (3 + 4*2); + return code; +} + +static int SizeDumpVnode(register struct iod *iodp, struct VnodeDiskObject *v, int volid, int vnodeNumber, int dumpEverything, + register struct volintSize *v_size) +{ + int code = 0; + + if (!v || v->type == vNull) + return code; +/* if (!code) code = DumpDouble(iodp, D_VNODE, vnodeNumber, v->uniquifier); */ + v_size->dump_size += 9; + if (!dumpEverything) + return code; +/* if (!code) code = DumpByte(iodp, 't',(byte)v->type); */ + v_size->dump_size += 2; +/* if (!code) code = DumpShort(iodp, 'l', v->linkCount); /\* May not need this *\/ */ + v_size->dump_size += 3; +/* if (!code) code = DumpInt32(iodp, 'v', v->dataVersion); */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 'm', v->unixModifyTime); */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 'a', v->author); */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 'o', v->owner); */ + v_size->dump_size += 5; +/* if (!code && v->group) code = DumpInt32(iodp, 'g', v->group); /\* default group is 0 *\/ */ + if(v->group) v_size->dump_size += 5; +/* if (!code) code = DumpShort(iodp, 'b', v->modeBits); */ + v_size->dump_size += 3; +/* if (!code) code = DumpInt32(iodp, 'p', v->parent); */ + v_size->dump_size += 5; +/* if (!code) code = DumpInt32(iodp, 's', v->serverModifyTime); */ + v_size->dump_size += 5; + if (v->type == vDirectory) { +/* acl_HtonACL(VVnodeDiskACL(v)); */ +/* if (!code) code = DumpByteString(iodp, 'A', (byte *) VVnodeDiskACL(v), VAclDiskSize(v)); */ + v_size->dump_size += 1 + VAclDiskSize(v); + } + + if (VNDISK_GET_INO(v)) { + v_size->dump_size += (v->length + 5); + } + return code; +} + +/* A partial dump (no dump header) */ +static int SizeDumpPartial(register struct iod *iodp, register Volume *vp, afs_int32 fromtime, int dumpAllDirs, + register struct volintSize *v_size) +{ + int code = 0; + if (!code) code = SizeDumpVolumeHeader(iodp, vp, v_size); + if (!code) code = SizeDumpVnodeIndex(iodp, vp, vLarge, fromtime, dumpAllDirs, v_size); + if (!code) code = SizeDumpVnodeIndex(iodp, vp, vSmall, fromtime, 0, v_size); + return code; +} + +static int SizeDumpVnodeIndex(register struct iod *iodp, Volume *vp, VnodeClass class, afs_int32 fromtime, + int forcedump, register struct volintSize *v_size) +{ + register int code = 0; + register struct VnodeClassInfo *vcp = &VnodeClassInfo[class]; + char buf[SIZEOF_LARGEDISKVNODE]; + struct VnodeDiskObject *vnode = (struct VnodeDiskObject *) buf; + StreamHandle_t *file; + FdHandle_t *fdP; + int size; + int flag; + register int vnodeIndex, nVnodes; + + fdP = IH_OPEN(vp->vnodeIndex[class].handle); + assert(fdP != NULL); + file = FDH_FDOPEN(fdP, "r+"); + assert(file != NULL); + size = OS_SIZE(fdP->fd_fd); + assert(size != -1); + nVnodes = (size / vcp->diskSize) - 1; + if (nVnodes > 0) { + assert((nVnodes+1)*vcp->diskSize == size); + assert(STREAM_SEEK(file, vcp->diskSize, 0) == 0); + } + else nVnodes = 0; + for (vnodeIndex = 0; nVnodes && STREAM_READ(vnode, vcp->diskSize, 1, file) == 1 && !code; + nVnodes--, vnodeIndex++) { + flag = forcedump || (vnode->serverModifyTime >= fromtime); + /* Note: the >= test is very important since some old volumes may not have + a serverModifyTime. For an epoch dump, this results in 0>=0 test, which + does dump the file! */ + if (!code) code = SizeDumpVnode(iodp, vnode, V_id(vp), bitNumberToVnodeNumber(vnodeIndex, class), flag, v_size); + } + STREAM_CLOSE(file); + FDH_CLOSE(fdP); + return code; +} + diff --git a/src/volser/volint.xg b/src/volser/volint.xg index a467757..cfa5155 100644 --- a/src/volser/volint.xg +++ b/src/volser/volint.xg @@ -48,6 +48,7 @@ statindex 16 #define VOLXLISTPARTITIONS 127 #define VOLFORWARDMULTIPLE 128 #define VOLCONVERTRO 65536 +#define VOLGETSIZE 65537 const SIZE = 1024; @@ -216,6 +217,11 @@ struct replica { struct destServer server; }; +/* Various size parameters of the volume */ +struct volintSize { + afs_uint64 dump_size; +}; + typedef replica manyDests<>; typedef afs_int32 manyResults<>; typedef transDebugInfo transDebugEntries<>; @@ -396,3 +402,9 @@ proc ConvertROtoRWvolume( IN afs_int32 partid, IN afs_int32 volid ) = VOLCONVERTRO; + +proc GetSize( + IN afs_int32 fromTrans, + IN afs_int32 fromDate, + OUT struct volintSize *size +) = VOLGETSIZE; diff --git a/src/volser/volprocs.c b/src/volser/volprocs.c index 20658a6..9ffffcd 100644 --- a/src/volser/volprocs.c +++ b/src/volser/volprocs.c @@ -2801,6 +2801,33 @@ afs_int32 SAFSVolConvertROtoRWvolume(acid, partId, volumeId) #endif /* AFS_NAMEI_ENV */ } +afs_int32 SAFSVolGetSize (acid, fromTrans, fromDate, size) +struct rx_call *acid; +afs_int32 fromTrans; +afs_int32 fromDate; +register struct volintSize *size; +{ + int code = 0; + register struct volser_trans *tt; + char caller[MAXKTCNAMELEN]; + + if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/ + tt = FindTrans(fromTrans); + if (!tt) return ENOENT; + if (tt->vflags & VTDeleted) { + TRELE(tt); + return ENOENT; + } + strcpy(tt->lastProcName,"GetSize"); + tt->rxCallPtr = acid; + code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size); /* measure volume's data */ + tt->rxCallPtr = (struct rx_call *)0; + if(TRELE(tt)) return VOLSERTRELE_ERROR; + +/* osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END); */ + return code; +} + /* GetPartName - map partid (a decimal number) into pname (a string) * Since for NT we actually want to return the drive name, we map through the * partition struct. diff --git a/src/volser/vos.c b/src/volser/vos.c index d1f9519..d3140f1 100644 --- a/src/volser/vos.c +++ b/src/volser/vos.c @@ -4334,6 +4334,80 @@ register struct cmd_syndesc *as; return code; } +static Sizes(as) +register struct cmd_syndesc *as; +{ + afs_int32 avolid, aserver, apart,voltype,fromdate=0,code, err, i; + struct nvldbentry entry; + volintSize vol_size; + + rx_SetRxDeadTime(60 * 10); + for (i = 0; iservice) rxConn->service->connDeadTime = rx_connDeadTime; + } + + avolid = vsu_GetVolumeID(as->parms[0].items->data, cstruct, &err); + if (avolid == 0) { + if (err) PrintError("", err); + else fprintf(STDERR, "vos: can't find volume '%s'\n", as->parms[0].items->data); + return ENOENT; + } + + if (as->parms[1].items || as->parms[2].items) { + if (!as->parms[1].items || !as->parms[2].items) { + fprintf(STDERR, "Must specify both -server and -partition options\n"); + return -1; + } + aserver = GetServer(as->parms[2].items->data); + if (aserver == 0) { + fprintf(STDERR, "Invalid server name\n"); + return -1; + } + apart = volutil_GetPartitionID(as->parms[1].items->data); + if (apart < 0) { + fprintf(STDERR, "Invalid partition name\n"); + return -1; + } + } else { + code = GetVolumeInfo(avolid, &aserver, &apart, &voltype, &entry); + if (code) return code; + } + + fromdate = 0; + + if (as->parms[4].items && strcmp(as->parms[4].items->data,"0")) { + code = ktime_DateToInt32(as->parms[4].items->data, &fromdate); + if (code) { + fprintf(STDERR,"vos: failed to parse date '%s' (error=%d))\n", + as->parms[1].items->data, code); + return code; + } + } + + fprintf(STDOUT, "Volume: %s\n", as->parms[0].items->data); + + if(as->parms[3].items) /* do the dump estimate */ + { + vol_size.dump_size = 0; + code = UV_GetSize(avolid, aserver, apart, fromdate, &vol_size); + if (code) { + PrintDiagnostics("size", code); + return code; + } + /* presumably the size info is now gathered in pntr */ + /* now we display it */ + + fprintf(STDOUT,"dump_size: %llu\n", vol_size.dump_size); + } + + /* Display info */ + + return 0; +} + PrintDiagnostics(astring, acode) char *astring; afs_int32 acode; @@ -4643,6 +4717,14 @@ char **argv; { cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL, "don't ask"); COMMONPARMS; + ts = cmd_CreateSyntax("size", Sizes, 0, "obtain various sizes of the volume."); + cmd_AddParm(ts, "-id", CMD_SINGLE, 0, "volume name or ID"); + cmd_AddParm(ts, "-partition", CMD_SINGLE, CMD_OPTIONAL, "partition name"); + cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_OPTIONAL, "machine name"); + cmd_AddParm(ts, "-dump", CMD_FLAG, CMD_OPTIONAL, "Obtain the size of the dump"); + cmd_AddParm(ts, "-time", CMD_SINGLE, CMD_OPTIONAL, "dump from time"); + COMMONPARMS; + code = cmd_Dispatch(argc, argv); if (rxInitDone) { /* Shut down the ubik_client and rx connections */ diff --git a/src/volser/vsprocs.c b/src/volser/vsprocs.c index 39f7f02..ebe614c 100644 --- a/src/volser/vsprocs.c +++ b/src/volser/vsprocs.c @@ -5657,6 +5657,45 @@ int UV_SetVolumeInfo(afs_int32 server, afs_int32 partition, afs_int32 volid, vol return(error); } +int UV_GetSize(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart, + afs_int32 fromdate, struct volintSize *vol_size) +{ + struct rx_connection *aconn = (struct rx_connection *)0; + afs_int32 tid=0, rcode=0; + afs_int32 code, error = 0; + + + /* get connections to the servers */ + aconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT); + + VPRINT1("Starting transaction on volume %u...", afromvol); + code = AFSVolTransCreate(aconn, afromvol, afrompart, ITBusy, &tid); + EGOTO1(error_exit, code, "Could not start transaction on the volume %u to be measured\n", afromvol); + VDONE; + + VPRINT1("Getting size of volume on volume %u...", afromvol); + code = AFSVolGetSize(aconn, tid, fromdate, vol_size); + EGOTO(error_exit, code, "Could not start the measurement process \n"); + VDONE; + + error_exit: + if (tid) { + VPRINT1("Ending transaction on volume %u...", afromvol); + code = AFSVolEndTrans(aconn, tid, &rcode); + if (code || rcode) { + fprintf(STDERR,"Could not end transaction on the volume %u\n", afromvol); + fprintf(STDERR,"error codes: %d and %d\n", code, rcode); + if (!error) error = (code?code:rcode); + } + VDONE; + } + if (aconn) + rx_DestroyConnection(aconn); + + PrintError("", error); + return(error); +} + /*maps the host addresses in (present in network byte order) to that in< new> (present in host byte order )*/ void MapNetworkToHost(struct nvldbentry *old, struct nvldbentry *new) -- 1.9.4