#include <errno.h>
#define ERRCODE_RANGE 8 /* from error_table.h */
#define CLOCKSKEW 2 /* not really skew, but resolution */
+#define CLOCKADJ(x) (((x) < CLOCKSKEW) ? 0 : (x) - CLOCKSKEW)
/* for UV_MoveVolume() recovery */
int verbose = 0;
struct release {
- afs_int32 time;
+ afs_int32 crtime;
+ afs_int32 uptime;
afs_int32 vldbEntryIndex;
};
afs_int32 flags);
static int GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index,
struct rx_connection **connPtr, afs_int32 * transPtr,
- afs_int32 * timePtr);
+ afs_int32 * crtimePtr, afs_int32 * uptimePtr);
static int SimulateForwardMultiple(struct rx_connection *fromconn,
afs_int32 fromtid, afs_int32 fromdate,
manyDests * tr, afs_int32 flags,
void *cookie, manyResults * results);
-static int rel_compar(struct release *r1, struct release *r2);
static afs_int32 CheckVolume(volintInfo * volumeinfo, afs_int32 aserver,
afs_int32 apart, afs_int32 * modentry,
afs_uint32 * maxvolid);
return 0;
}
+void init_volintInfo(struct volintInfo *vinfo) {
+ memset(vinfo, 0, sizeof(struct volintInfo));
+
+ vinfo->maxquota = -1;
+ vinfo->dayUse = -1;
+ vinfo->creationDate = -1;
+ vinfo->updateDate = -1;
+ vinfo->flags = -1;
+ vinfo->spare0 = -1;
+ vinfo->spare1 = -1;
+ vinfo->spare2 = -1;
+ vinfo->spare3 = -1;
+}
static struct rx_securityClass *uvclass = 0;
static int uvindex = -1;
tid = 0;
aconn = (struct rx_connection *)0;
error = 0;
- memset(&tstatus, 0, sizeof(struct volintInfo));
- tstatus.dayUse = -1;
+
+ init_volintInfo(&tstatus);
tstatus.maxquota = aquota;
aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
newVol);
VDONE;
- fromDate = tstatus.creationDate - CLOCKSKEW;
+ fromDate = CLOCKADJ(tstatus.creationDate);
} else {
/* With RV_NOCLONE, just do a full copy from the source */
fromDate = 0;
infop = (volintInfo *) volumeInfo.volEntries_val;
infop->maxquota = -1; /* Else it will replace the default quota */
+ infop->creationDate = -1; /* Else it will use the source creation date */
+ infop->updateDate = -1; /* Else it will use the source update date */
#endif
/* create a volume on the target machine */
cloneVol);
VDONE;
- fromDate = tstatus.creationDate - CLOCKSKEW;
+ fromDate = CLOCKADJ(tstatus.creationDate);
} else {
fromDate = 0;
}
VDONE;
/* Using the update date should be OK here, but add some fudge */
- cloneFromDate = tstatus.updateDate - CLOCKSKEW;
+ cloneFromDate = CLOCKADJ(tstatus.updateDate);
if ((flags & RV_NOCLONE))
fromDate = cloneFromDate;
static int
GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index,
struct rx_connection **connPtr, afs_int32 * transPtr,
- afs_int32 * timePtr)
+ afs_int32 * crtimePtr, afs_int32 * uptimePtr)
{
afs_int32 volid;
struct volser_status tstatus;
int code, rcode, tcode;
*connPtr = (struct rx_connection *)0;
- *timePtr = 0;
*transPtr = 0;
+ *crtimePtr = 0;
+ *uptimePtr = 0;
/* get connection to the replication site */
*connPtr = UV_Bind(vldbEntryPtr->serverNumber[index], AFSCONF_VOLUMEPORT);
code);
goto fail;
}
- *timePtr = tstatus.creationDate - CLOCKSKEW;
+ *crtimePtr = CLOCKADJ(tstatus.creationDate);
+ *uptimePtr = CLOCKADJ(tstatus.updateDate);
}
return 0;
}
-static int
-rel_compar(struct release *r1, struct release *r2)
-{
- return (r1->time - r2->time);
-}
-
/* UV_ReleaseVolume()
* Release volume <afromvol> on <afromserver> <afrompart> to all
* its RO sites (full release). Unless the previous release was
manyDests tr;
manyResults results;
int rwindex, roindex, roclone, roexists;
- afs_int32 rwcrdate, clcrdate;
+ afs_int32 rwcrdate, rwupdate, clcrdate;
struct rtime {
int validtime;
- afs_uint32 time;
+ afs_uint32 uptime;
} remembertime[NMAXNSERVERS];
int releasecount = 0;
struct volser_status volstatus;
ONERROR(code, afromvol,
"Failed to get the status of RW volume %u\n");
rwcrdate = volstatus.creationDate;
+ rwupdate = volstatus.updateDate;
/* End transaction on RW */
code = AFSVolEndTrans(fromconn, fromtid, &rcode);
"Failed to get the status of RW clone %u\n");
clcrdate = volstatus.creationDate;
- /* End transaction on RW */
+ /* End transaction on clone */
code = AFSVolEndTrans(fromconn, clonetid, &rcode);
clonetid = 0;
ONERROR((code ? code : rcode), cloneVolId,
- "Failed to end transaction on RW volume %u\n");
+ "Failed to end transaction on RW clone %u\n");
if (rwcrdate > clcrdate)
fullrelease = 2;/* Do a full release if RO clone older than RW */
if (roclone) {
strcpy(vname, entry.name);
strcat(vname, ".readonly");
- VPRINT("Cloning RW volume %u to permanent RO...");
+ VPRINT1("Cloning RW volume %u to permanent RO...", afromvol);
} else {
strcpy(vname, "readonly-clone-temp");
- VPRINT("Cloning RW volume %u to temporary RO...");
+ VPRINT1("Cloning RW volume %u to temporary RO...", afromvol);
}
code =
AFSVolClone(fromconn, clonetid, 0, readonlyVolume, vname,
}
/* Get the time the RW was created for future information */
- VPRINT1("Getting status of RW volume %u...", cloneVolId);
+ VPRINT1("Getting status of RW volume %u...", afromvol);
code = AFSVolGetStatus(fromconn, clonetid, &volstatus);
- ONERROR(code, cloneVolId,
+ ONERROR(code, afromvol,
"Failed to get the status of the RW volume %u\n");
VDONE;
rwcrdate = volstatus.creationDate;
+ rwupdate = volstatus.updateDate;
/* End the transaction on the RW volume */
- VPRINT1("Ending cloning transaction on RW volume %u...", cloneVolId);
+ VPRINT1("Ending cloning transaction on RW volume %u...", afromvol);
code = AFSVolEndTrans(fromconn, clonetid, &rcode);
clonetid = 0;
- ONERROR((code ? code : rcode), cloneVolId,
+ ONERROR((code ? code : rcode), afromvol,
"Failed to end cloning transaction on RW %u\n");
VDONE;
code =
GetTrans(&entry, vldbindex, &(toconns[volcount]),
&(replicas[volcount].trans),
- &(times[volcount].time));
+ &(times[volcount].crtime),
+ &(times[volcount].uptime));
if (code)
continue;
/* Thisdate is the date from which we want to pick up all changes */
if (forceflag || !fullrelease
- || (rwcrdate > times[volcount].time)) {
+ || (rwcrdate > times[volcount].crtime)) {
/* If the forceflag is set, then we want to do a full dump.
* If it's not a full release, we can't be sure that the creation
* date is good (so we also do a full dump).
* case time[volcount].time would be now instead of 0.
*/
thisdate =
- (remembertime[vldbindex].time <
- times[volcount].time) ? remembertime[vldbindex].
- time : times[volcount].time;
+ (remembertime[vldbindex].uptime < times[volcount].uptime)
+ ? remembertime[vldbindex].uptime
+ : times[volcount].uptime;
} else {
- thisdate = times[volcount].time;
+ thisdate = times[volcount].uptime;
}
remembertime[vldbindex].validtime = 1;
- remembertime[vldbindex].time = thisdate;
+ remembertime[vldbindex].uptime = thisdate;
if (volcount == 0) {
fromdate = thisdate;
if (fromdate == 0)
fprintf(STDOUT, " (full release)");
+ else
+ fprintf(STDOUT, " (as of %.24s)", ctime((time_t *)&fromdate));
fprintf(STDOUT, ".\n");
fflush(STDOUT);
}
* after extracting params from the rock
*/
int
-UV_RestoreVolume(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
- char tovolname[], int flags, afs_int32(*WriteData) (),
- char *rock)
+UV_RestoreVolume2(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
+ afs_int32 toparentid, char tovolname[], int flags,
+ afs_int32(*WriteData) (), char *rock)
{
struct rx_connection *toconn, *tempconn;
struct rx_call *tocall;
afs_int32 totid, code, rcode, vcode, terror = 0;
afs_int32 rxError = 0;
struct volser_status tstatus;
+ struct volintInfo vinfo;
char partName[10];
- afs_int32 pvolid;
+ afs_int32 pvolid, pparentid;
afs_int32 temptid;
int success;
struct nvldbentry entry, storeEntry;
int islocked;
struct restoreCookie cookie;
int reuseID;
- afs_int32 newDate, volflag, voltype, volsertype;
+ afs_int32 volflag, voltype, volsertype;
+ afs_int32 oldCreateDate, oldUpdateDate, newCreateDate, newUpdateDate;
int index, same, errcode;
char apartName[10];
}
pvolid = tovolid;
+ pparentid = toparentid;
toconn = UV_Bind(toserver, AFSCONF_VOLUMEPORT);
if (pvolid == 0) { /*alot a new id if needed */
vcode = VLDB_GetEntryByName(tovolname, &entry);
goto refail;
}
pvolid = entry.volumeId[ROVOL];
+ pparentid = entry.volumeId[RWVOL];
} else {
pvolid = entry.volumeId[RWVOL];
+ pparentid = entry.volumeId[RWVOL];
}
}
+ if (!pparentid) pparentid = pvolid;
/* at this point we have a volume id to use/reuse for the volume to be restored */
if (strlen(tovolname) > (VOLSER_OLDMAXVOLNAME - 1)) {
EGOTO1(refail, VOLSERBADOP,
hostutil_GetNameByINet(toserver), partName);
fflush(STDOUT);
code =
- AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0, &pvolid,
+ AFSVolCreateVolume(toconn, topart, tovolname, volsertype, pparentid, &pvolid,
&totid);
if (code) {
if (flags & RV_FULLRST) { /* full restore: delete then create anew */
EGOTO1(refail, code, "Failed to start transaction on %u\n",
pvolid);
+ code = AFSVolGetStatus(toconn, totid, &tstatus);
+ EGOTO1(refail, code, "Could not get timestamp from volume %u\n",
+ pvolid);
+
+ oldCreateDate = tstatus.creationDate;
+ oldUpdateDate = tstatus.updateDate;
+
code =
AFSVolSetFlags(toconn, totid,
VTDeleteOnSalvage | VTOutOfService);
VDONE;
code =
- AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0,
+ AFSVolCreateVolume(toconn, topart, tovolname, volsertype, pparentid,
&pvolid, &totid);
EGOTO1(refail, code, "Could not create new volume %u\n", pvolid);
-
- newDate = 0;
} else {
code =
AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
code = AFSVolGetStatus(toconn, totid, &tstatus);
EGOTO1(refail, code, "Could not get timestamp from volume %u\n",
pvolid);
- newDate = tstatus.creationDate;
+
+ oldCreateDate = tstatus.creationDate;
+ oldUpdateDate = tstatus.updateDate;
}
+ } else {
+ oldCreateDate = 0;
+ oldUpdateDate = 0;
}
- cookie.parent = pvolid;
+
+ cookie.parent = pparentid;
cookie.type = voltype;
cookie.clone = 0;
strncpy(cookie.name, tovolname, VOLSER_OLDMAXVOLNAME);
error = code;
goto refail;
}
- code = AFSVolSetIdsTypes(toconn, totid, tovolname, voltype, pvolid, 0, 0);
+ code = AFSVolSetIdsTypes(toconn, totid, tovolname, voltype, pparentid, 0, 0);
if (code) {
fprintf(STDERR, "Could not set the right type and ID on %lu\n",
(unsigned long)pvolid);
error = code;
goto refail;
}
- if (!newDate)
- newDate = time(0);
- code = AFSVolSetDate(toconn, totid, newDate);
+
+ if (flags & RV_CRDUMP)
+ newCreateDate = tstatus.creationDate;
+ else if (flags & RV_CRKEEP && oldCreateDate != 0)
+ newCreateDate = oldCreateDate;
+ else
+ newCreateDate = time(0);
+ if (flags & RV_LUDUMP)
+ newUpdateDate = tstatus.updateDate;
+ else if (flags & RV_LUKEEP)
+ newUpdateDate = oldUpdateDate;
+ else
+ newUpdateDate = time(0);
+ code = AFSVolSetDate(toconn,totid, newCreateDate);
if (code) {
- fprintf(STDERR, "Could not set the date on %lu\n",
- (unsigned long)pvolid);
+ fprintf(STDERR, "Could not set the 'creation' date on %u\n", pvolid);
+ error = code;
+ goto refail;
+ }
+
+ init_volintInfo(&vinfo);
+ vinfo.creationDate = newCreateDate;
+ vinfo.updateDate = newUpdateDate;
+ code = AFSVolSetInfo(toconn, totid, &vinfo);
+ if (code) {
+ fprintf(STDERR, "Could not set the 'last updated' date on %u\n",
+ pvolid);
error = code;
goto refail;
}
entry.volumeId[ROVOL] = tstatus.cloneID; /*this should come from status info on the volume if non zero */
} else
entry.volumeId[ROVOL] = INVALID_BID;
- entry.volumeId[RWVOL] = pvolid;
+ entry.volumeId[RWVOL] = pparentid;
entry.cloneId = 0;
if (tstatus.backupID != 0) {
entry.volumeId[BACKVOL] = tstatus.backupID;
return error;
}
+int
+UV_RestoreVolume(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
+ char tovolname[], int flags, afs_int32(*WriteData) (),
+ char *rock)
+{
+ return UV_RestoreVolume2(toserver, topart, tovolid, 0, tovolname, flags,
+ WriteData, rock);
+}
+
/*unlocks the vldb entry associated with <volid> */
int