Rubino Gei� wrote:
> Hi,
>
> this is exactly what we want. Doing something like "vos dump | vos
> restore" cost far too much time, I guess. My concern is to get our
> systems productive in case a major failure make one of the main servers
> unusable. dump / restore is usable in case one volume get accidentally
> killed / deleted, but not for restoring >> 100 GB and hundreds of
> volumes...
>
> Hartmut, can you publish the changes you made to MR-AFS so we can
> integrate it into OpenAFS? Or does someone did this??? I'm sure a lot of
> people would like to get this working.
>
>
> Bye, ruby
>
Ok, here are the changes stripped from MR-AFS specific code. I admit
that this was quick and durty programming, but who ever want's may
improve it.
In vos .c:
####################################################################################
static ConvertRO(as)
register struct cmd_syndesc *as;
{
afs_int32 partition = -1;
afs_int32 server, volid, code, i, same;
struct nvldbentry entry, storeEntry;
afs_int32 vcode;
afs_int32 rwindex;
afs_int32 rwserver = 0;
afs_int32 rwpartition;
afs_int32 roindex;
afs_int32 roserver = 0;
afs_int32 ropartition;
int force = 0;
struct rx_connection *aconn;
char c, dc;
server = GetServer(as->parms[0].items->data);
if (!server) {
fprintf(STDERR,"vos: host '%s' not found in host
table\n",as->parms[0].items->data );
return ENOENT;
}
partition = volutil_GetPartitionID(as->parms[1].items->data);
if (partition < 0) {
fprintf(STDERR,"vos: could not interpret partition name
'%s'\n",as->parms[1].items->data );
return ENOENT;
}
if (!IsPartValid(partition, server, &code)) {
if(code) PrintError("",code);
else fprintf(STDERR,"vos : partition %s does not exist on the
server\n",as->parms[1].items->data);
return ENOENT;
}
volid = vsu_GetVolumeID(as->parms[2].items->data, cstruct, &code);
if (volid == 0) {
if (code) PrintError("", code);
else fprintf(STDERR, "Unknown volume ID or name '%s'\n",
as->parms[0].items->data);
return -1;
}
if (as->parms[3].items)
force = 1;
vcode = VLDB_GetEntryByID (volid, -1, &entry);
if(vcode) {
fprintf(STDERR,"Could not fetch the entry for volume %u from
VLDB\n",
volid);
PrintError("convertROtoRW", code);
return vcode;
}
/* use RO volid even if user specified RW or BK volid */
if (volid != entry.volumeId[ROVOL])
volid = entry.volumeId[ROVOL];
MapHostToNetwork(&entry);
for (i=0; i< entry.nServers; i++) {
if (entry.serverFlags[i] & ITSRWVOL) {
rwindex = i;
rwserver = entry.serverNumber[i];
rwpartition = entry.serverPartition[i];
}
if (entry.serverFlags[i] & ITSROVOL) {
same = VLDB_IsSameAddrs(server, entry.serverNumber[i], &code);
if (code) {
fprintf(STDERR, "Failed to get info about server's %d
address(es) from vlserver (err=%d); aborting call!\n",
server, code);
return ENOENT;
}
if (same) {
roindex = i;
roserver = entry.serverNumber[i];
ropartition = entry.serverPartition[i];
break;
}
}
}
if (!roserver) {
fprintf(STDERR, "Warning: RO volume didn't exist in vldb!\n");
}
if (ropartition != partition) {
fprintf(STDERR, "Warning: RO volume should be in partition %d
instead of %d (vldb)\n", ropartition, partition);
}
if (rwserver) {
fprintf(STDERR,
"VLDB indicates that a RW volume exists already on %s
in partition %s.\n");
if (!force) {
fprintf(STDERR, "Overwrite this VLDB entry? [y|n] (n)\n");
dc = c = getchar();
while (!(dc==EOF || dc=='\n')) dc=getchar(); /* goto end of
line */
if ((c != 'y') && (c != 'Y')) {
fprintf(STDERR, "aborted.\n");
return -1;
}
}
}
vcode = ubik_Call(VL_SetLock, cstruct, 0, entry.volumeId[RWVOL], RWVOL,
VLOP_MOVE);
aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
code = AFSVolConvertROtoRWvolume(aconn, partition, volid);
if (code) {
fprintf(STDERR,"Converting RO volume %u to RW volume failed
with code %d\n", volid, code);
PrintError("convertROtoRW", code);
return -1;
}
entry.serverFlags[roindex] = ITSRWVOL;
entry.flags |= RW_EXISTS;
entry.flags &= ~BACK_EXISTS;
if (rwserver) {
(entry.nServers)--;
if (rwindex != entry.nServers) {
entry.serverNumber[rwindex] =
entry.serverNumber[entry.nServers];
entry.serverPartition[rwindex] =
entry.serverPartition[entry.nServers];
entry.serverFlags[rwindex] = entry.serverFlags[entry.nServers];
entry.serverNumber[entry.nServers] = 0;
entry.serverPartition[entry.nServers] = 0;
entry.serverFlags[entry.nServers] = 0;
}
}
entry.flags &= ~RO_EXISTS;
for (i=0; i<entry.nServers; i++) {
if (entry.serverFlags[i] & ITSROVOL) {
if (!(entry.serverFlags[i] & (RO_DONTUSE | NEW_REPSITE)))
entry.flags |= RO_EXISTS;
}
}
MapNetworkToHost(&entry, &storeEntry);
code = VLDB_ReplaceEntry(entry.volumeId[RWVOL], RWVOL, &storeEntry,
(LOCKREL_OPCODE | LOCKREL_AFSID |
LOCKREL_TIMESTAMP));
if (code) {
fprintf(STDERR, "Warning: volume converted, but vldb update
failed with
code %d!\n", code);
}
vcode = UV_LockRelease(entry.volumeId[RWVOL]);
if (vcode) {
PrintDiagnostics("unlock", vcode);
}
return code;
}
##################################################################################
and later:
##################################################################################
ts = cmd_CreateSyntax("convertROtoRW", ConvertRO, 0, "convert a RO
volume into a RW volume (after loss of old RW volume)");
cmd_AddParm(ts, "-server", CMD_SINGLE,CMD_OPTIONAL, "machine name");
cmd_AddParm(ts, "-partition", CMD_SINGLE,CMD_OPTIONAL, "partition
name");
cmd_AddParm(ts, "-id", CMD_SINGLE, 0, "volume name or ID");
cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL, "don't ask");
COMMONPARMS;
###################################################################################
in volprocs.c
afs_int32 SAFSVolConvertROtoRWvolume(acid, partId, volumeId)
struct rx_call *acid;
afs_int32 partId;
afs_int32 volumeId;
{
#ifdef AFS_NAMEI_ENV
register struct Volume *tv;
struct volser_trans *ttc;
DIR *dirp;
char pname[16];
char volname[20];
afs_int32 error = 0;
afs_int32 volid;
int found = 0;
unsigned int now;
char caller[MAXKTCNAMELEN];
char headername[16];
char tpath[256];
struct VolumeDiskHeader h;
int fd;
IHandle_t *ih;
Inode ino;
if (!afsconf_SuperUser(tdir, acid, caller)) return
VOLSERBAD_ACCESS;/*not a super user*/
if(GetPartName(partId, pname)) return VOLSERILLEGAL_PARTITION;
dirp = opendir(pname);
if(dirp == NULL) return VOLSERILLEGAL_PARTITION;
strcpy(volname,"");
while(strcmp(volname,"EOD") && !found){/*while there are more
volumes in the partition */
if(!strcmp(volname,"")) {/* its not a volume, fetch next file */
GetNextVol(dirp,pname,volname,&volid);
continue; /*back to while loop */
}
if(volid == volumeId)
found = 1;
}
if (!found) {
return ENOENT;
}
sprintf((char *)&headername, VFORMAT, volumeId);
sprintf((char *)&tpath,"%s/%s", pname, headername);
fd = open(tpath, O_RDONLY);
if (fd < 0) {
LogErrors(0,"SAFS_VolConvertROtoRWvolume: Couldn't open header
for RO-volume %lu.\n", volumeId);
return ENOENT;
}
if (read(fd, &h, sizeof(h)) != sizeof(h)) {
LogErrors(0,"SAFS_VolConvertROtoRWvolume: Couldn't read header
for RO-volume %lu.\n", volumeId);
return EIO;
}
close(fd);
FSYNC_askfs(volumeId, partId, FSYNC_RESTOREVOLUME, 0);
ino = NAMEI_INODESPECIAL;
ino |= ((Inode)VI_LINKTABLE) << NAMEI_TAGSHIFT;
ino |= ((Inode)h.parent) << NAMEI_UNIQSHIFT;
IH_INIT(ih,
FSList.FileSystemsList_val[i].FileSystems_u.AfsInodeInterface.DeviceTagNumber,
h.parent, ino);
code = namei_ConvertROtoRWvolume(ih, volumeId, &convertVolumeInfo);
if (code)
return code;
if (unlink(tpath) < 0) {
LogErrors(0, "SAFS_VolConvertROtoRWvolume: Couldn't unlink RO
header, error = %d\n", error);
}
h.id = h.parent;
h.volumeInfoFileTag2 = h.id;
h.smallVnodeFileTag2 = h.id;
h.largeVnodeFileTag2 = h.id;
h.linkTableFileTag2 = h.id;
sprintf((char *)&headername, VFORMAT, h.id);
sprintf((char *)&tpath, "%s/%s", pname, headername);
fd = open(tpath, O_CREAT | O_EXCL | O_RDWR, 0644);
if (fd < 0) {
LogErrors(0,"SAFS_VolConvertROtoRWvolume: Couldn't create
header for RW-volume %lu.\n", h.id);
return EIO;
}
if (write(fd, &h, sizeof(h)) != sizeof(h)) {
LogErrors(0,"SAFS_VolConvertROtoRWvolume: Couldn't write header
for RW-volume %lu.\n", h.id);
return EIO;
}
close(fd);
FSYNC_askfs(volumeId, partId, FSYNC_DONE, 0);
FSYNC_askfs(h.id, partId, FSYNC_ON, 0);
return 0;
#else /* AFS_NAMEI_ENV */
return EINV;
#endif /* AFS_NAMEI_ENV */
}
#####################################################################################
in volint.xg:
#####################################################################################
#define VOLCONVERTRO 141
proc ConvertROtoRWvolume(
IN afs_int32 partid,
IN afs_int32 volid
) = VOLCONVERTRO;
#####################################################################################
in namei_ops.c:
#####################################################################################
/*
* Convert a RO-volume into a RW-volume
*
* This function allows to recover very fast from the loss of a partition
* if from RO-copies exist of all volumes exist on another partition.
* Then these RO-volumes can be made to the new RW-volumes.
* Backup of RW-volumes consists in "vos release".
*
* We must mke sure in this partition exists only the RO-volume which
* is typical for remote replicas.
*
* Then the linktable is already ok,
* the vnode files need to be renamed
* the volinfo file needs to be replaced by another one with
* slightly different contents and new name.
* The volume header file of the RO-volume in the /vicep<x> directory
* is destroyed by this call. A new header file for the RW-volume must
* be created after return from this routine.
*/
int namei_ConvertROtoRWvolume(IHandle_t * h, afs_uint32 vid,
int (*convertVolInfo)(int fd, int fd2, int vid))
{
namei_t n;
char dir_name[512], oldpath[512], newpath[512];
char smallName[64];
char largeName[64];
char infoName[64];
char tmp[NAMEI_LCOMP_LEN];
IHandle_t t_ih;
char infoSeen = 0;
char smallSeen = 0;
char largeSeen = 0;
char linkSeen = 0;
int code, fd, fd2;
char *p;
DIR *dirp;
struct dirent *dp;
struct ViceInodeInfo info;
namei_HandleToName(&n, h);
strcpy((char *) &dir_name, (char *) &n.n_path);
p = rindex((char *) &dir_name, '/');
*p = 0;
dirp = opendir(dir_name);
if (!dirp) {
LogErrors(0, "namei_ConvertROtoRWvolume: Could not opendir(%s)\n",
dir_name);
return EIO;
}
while (dp = readdir(dirp)) {
struct ViceInodeInfo info;
if (*dp->d_name == '.') continue;
if (DecodeInode((char *)&dir_name, dp->d_name, &info,
h->ih_vid)<0) {
LogErrors(0,"namei_ConvertROtoRWvolume: DecodeInode failed
for %s/%s\n", dir_name, dp->d_name);
closedir(dirp);
return -1;
}
if (info.u.param[1] != -1) {
LogErrors(0,"namei_ConvertROtoRWvolume: found other than
volume special file %s/%s\n", dir_name, dp->d_name);
closedir(dirp);
return -1;
}
if (info.u.param[0] != vid) {
if (info.u.param[0] == h->ih_vid) {
if (info.u.param[2] == 6) { /* link table */
linkSeen = 1;
continue;
}
}
LogErrors(0,"namei_ConvertROtoRWvolume: found special file
%s/%s for volume %lu\n", dir_name, dp->d_name, info.u.param[0]);
closedir(dirp);
return -1;
}
if (info.u.param[2] == 1) { /* volume info file */
strcpy((char *) &infoName, (char *) &dp->d_name);
infoSeen = 1;
}
else if (info.u.param[2] == 2) { /* small vnodes file */
strcpy((char *) &smallName, (char *) &dp->d_name);
smallSeen = 1;
}
else if (info.u.param[2] == 3) { /* large vnodes file */
strcpy((char *) &largeName, (char *) &dp->d_name);
largeSeen = 1;
}
else {
closedir(dirp);
LogErrors(0,"namei_ConvertROtoRWvolume: unknown type %d of
special file found : %s/%s\n", info.u.param[2], dir_name, dp->d_name);
return -1;
}
}
closedir(dirp);
if (!infoSeen || !smallSeen || !largeSeen || !linkSeen) {
LogErrors(0,"namei_ConvertROtoRWvolume: not all special files
found in %s\n", dir_name);
return -1;
}
/*
* If we come here then there was only a RO-volume and we can safely
* proceed.
*/
bzero(&t_ih, sizeof(t_ih));
t_ih.ih_dev = h->ih_dev;
t_ih.ih_vid = h->ih_vid;
sprintf(&oldpath, "%s/%s", dir_name, infoName);
fd = open(oldpath, O_RDWR, 0);
if (fd < 0) {
LogErrors(0,"namei_ConvertROtoRWvolume: could not open RO info
file: %s\n", oldpath);
return -1;
}
t_ih.ih_ino = namei_MakeSpecIno(h->ih_vid, 1);
namei_HandleToName(&n, &t_ih);
fd2 = open(n.n_path, O_CREAT|O_EXCL|O_TRUNC|O_RDWR, 0);
if (fd2 < 0) {
LogErrors(0,"namei_ConvertROtoRWvolume: could not create RW
info file: %s\n", n.n_path);
close(fd);
return -1;
}
code = (*convertVolInfo)(fd, fd2, h->ih_vid);
close(fd);
if (code) {
close(fd2);
unlink(n.n_path);
return -1;
}
SetOGM(fd2, h->ih_vid, 1);
close(fd2);
t_ih.ih_ino = namei_MakeSpecIno(h->ih_vid, 2);
namei_HandleToName(&n, &t_ih);
sprintf(&oldpath, "%s/%s", dir_name, smallName);
fd = open(oldpath, O_RDWR, 0);
SetOGM(fd, h->ih_vid, 2);
close(fd);
link(&oldpath, &n.n_path);
unlink(&oldpath);
t_ih.ih_ino = namei_MakeSpecIno(h->ih_vid, 3);
namei_HandleToName(&n, &t_ih);
sprintf(&oldpath, "%s/%s", dir_name, largeName);
fd = open(oldpath, O_RDWR, 0);
SetOGM(fd, h->ih_vid, 3);
close(fd);
link(&oldpath, &n.n_path);
unlink(&oldpath);
sprintf(&oldpath, "%s/%s", dir_name, infoName);
unlink(&oldpath);
return 0;
}
####################################################################################
I hope I didn't forget too much. If so, let me know.
Good luck!
Hartmut
-----------------------------------------------------------------
Hartmut Reuter e-mail [EMAIL PROTECTED]
phone +49-89-3299-1328
RZG (Rechenzentrum Garching) fax +49-89-3299-1301
Computing Center of the Max-Planck-Gesellschaft (MPG) and the
Institut fuer Plasmaphysik (IPP)
-----------------------------------------------------------------
_______________________________________________
OpenAFS-devel mailing list
[EMAIL PROTECTED]
https://lists.openafs.org/mailman/listinfo/openafs-devel