[OpenAFS] Re: status of "vos clone/shadow"?

Dan Hyde Dan Hyde <drh@umich.edu>
Thu, 28 Jun 2007 01:39:12 -0400


> Is there any place from which we can get the changes you made to the
> fileserver/dbserver code?

I just posted the following two patches:

Sorry for the delay.
-------------------------------------------------------------------------
The following patch(s) add a bit (byte) to the volume header (reserveb3
becomes volIsShadow).  This is used to prevent accidentially putting
shadow volumes into the VLDB.  It is also used to prevent non-admin
access to shadow volumes.

Thanks.
=========
diff -u viced/afsfileprocs.c viced/afsfileprocs.c
--- viced/afsfileprocs.c	2006-04-07 01:36:59.000000000 -0400
+++ viced/afsfileprocs.c	2006-07-17 22:01:16.000000000 -0400
@@ -739,6 +739,11 @@
     if (!VanillaUser(*client))
        (*rights) |= PRSFS_LOOKUP;
 #endif /* ADMIN_IMPLICIT_LOOKUP */
+    /* restrict access to shadow volumes */
+    if (V_volIsShadow(*volptr) && VanillaUser(*client)) {
+       (*rights) = (*anyrights) = 0;
+       return (EACCES);
+    }
     return errorCode;
 
 }                              /*GetVolumePackage */
diff -u vol/vol-info.c vol/vol-info.c
--- vol/vol-info.c	2005-05-08 02:10:27.000000000 -0400
+++ vol/vol-info.c	2006-06-28 13:05:13.000000000 -0400
@@ -692,6 +692,7 @@
 	 V_dayUse(vp), V_weekUse(vp)[0], V_weekUse(vp)[1], V_weekUse(vp)[2],
 	 V_weekUse(vp)[3], V_weekUse(vp)[4], V_weekUse(vp)[5],
 	 V_weekUse(vp)[6], date(V_dayUseDate(vp)));
+    printf("volIsShadow = %d\n", V_volIsShadow(vp));
 }
 
 /* GetFileInfo
diff -u vol/volume.h vol/volume.h
--- vol/volume.h	2005-05-30 00:41:29.000000000 -0400
+++ vol/volume.h	2006-06-28 13:05:13.000000000 -0400
@@ -225,7 +225,8 @@
 #define DONT_SALVAGE	0xE5
 #endif				/* ALPHA_DUX40_ENV */
     byte dontSalvage;		/* If this is on, then don't bother salvaging this volume */
-    byte reserveb3;
+    byte volIsShadow;		/* If this is on, this volume is a shadow of another volume.  Used
+				 * to make sure we don't accidentially populate the VLDB */
 
     bit32 reserved1[6];
 
@@ -373,6 +374,7 @@
 #define V_needsCallback(vp)	((vp)->header->diskstuff.needsCallback)
 #define V_destroyMe(vp)		((vp)->header->diskstuff.destroyMe)
 #define V_dontSalvage(vp)	((vp)->header->diskstuff.dontSalvage)
+#define V_volIsShadow(vp)	((vp)->header->diskstuff.volIsShadow)
 #define V_maxquota(vp)		((vp)->header->diskstuff.maxquota)
 #define V_minquota(vp)		((vp)->header->diskstuff.minquota)
 #define V_maxfiles(vp)		((vp)->header->diskstuff.maxfiles)
diff -u volser/volint.xg volser/volint.xg
--- volser/volint.xg	2003-06-19 12:06:58.000000000 -0400
+++ volser/volint.xg	2006-06-28 13:05:13.000000000 -0400
@@ -109,7 +109,7 @@
     afs_int32 spare0;		/* Used to hold the minquota value */
     afs_int32 spare1;		/* Used to hold the weekuse value */
     afs_int32 spare2;
-    afs_int32 spare3;
+    afs_int32 spare3;		/* Used to hold the unsigned char volIsShadow */
 };
 
 /*
diff -u volser/volprocs.c volser/volprocs.c
--- volser/volprocs.c	2006-01-24 22:25:49.000000000 -0500
+++ volser/volprocs.c	2006-06-28 13:05:13.000000000 -0400
@@ -1043,6 +1043,12 @@
     } else {
 	V_inService(vp) = 1;
     }
+
+    if (aflags & VTIsShadow) {
+	V_volIsShadow(vp) = 1;
+    } else if (aflags & VTNotShadow) {
+	V_volIsShadow(vp) = 0;
+    }
     VUpdateVolume(&error, vp);
     tt->vflags = aflags;
     tt->rxCallPtr = (struct rx_call *)0;
@@ -1544,6 +1550,8 @@
 	td->creationDate = astatus->creationDate;
     if (astatus->updateDate != -1)
 	td->updateDate = astatus->updateDate;
+    if (astatus->spare3 != -1)
+	td->volIsShadow = astatus->spare3;
     VUpdateVolume(&error, tv);
     tt->rxCallPtr = (struct rx_call *)0;
     if (TRELE(tt))
@@ -1849,7 +1857,8 @@
 		(long)tv->header->diskstuff.weekUse[4] +
 		(long)tv->header->diskstuff.weekUse[5] +
 		(long)tv->header->diskstuff.weekUse[6];
-	    pntr->flags = pntr->spare2 = pntr->spare3 = (long)0;
+	    pntr->flags = pntr->spare2 = (long)0;
+	    pntr->spare3 = tv->header->diskstuff.volIsShadow;
 	    VDetachVolume(&error, tv);	/*free the volume */
 	    tv = (Volume *) 0;
 	    if (error) {
@@ -2224,7 +2233,8 @@
 		(long)tv->header->diskstuff.weekUse[4] +
 		(long)tv->header->diskstuff.weekUse[5] +
 		(long)tv->header->diskstuff.weekUse[6];
-	    pntr->flags = pntr->spare2 = pntr->spare3 = (long)0;
+	    pntr->flags = pntr->spare2 = (long)0;
+	    pntr->spare3 = tv->header->diskstuff.volIsShadow;
 	    VDetachVolume(&error, tv);	/*free the volume */
 	    tv = (Volume *) 0;
 	    if (error) {
diff -u volser/volser.p.h volser/volser.p.h
--- volser/volser.p.h	2005-07-11 15:27:29.000000000 -0400
+++ volser/volser.p.h	2006-06-28 13:05:13.000000000 -0400
@@ -19,6 +19,8 @@
 #define	VTDeleteOnSalvage	1	/* delete on next salvage */
 #define	VTOutOfService		2	/* never put this volume online */
 #define	VTDeleted		4	/* deleted, don't do anything else */
+#define VTIsShadow		8	/* tag so we don't sync by mistake */
+#define VTNotShadow		0x10	/* tag so we don't sync by mistake */
 
 /* iflags, representing "attach mode" for this volume at the start of this transaction */
 #define	ITOffline	1	/* volume offline on server (returns VOFFLINE) */
@@ -169,6 +171,8 @@
 #define RV_CPINCR	0x20000
 #define RV_NOVLDB	0x40000
 #define RV_NOCLONE	0x80000
+#define RV_SETSHADOW	0x08000
+#define RV_CLRSHADOW	0x04000
 
 struct ubik_client;
 extern afs_uint32 vsu_GetVolumeID(char *astring, struct ubik_client *acstruct, afs_int32 *errp);
diff -u volser/vos.c volser/vos.c
--- volser/vos.c	2005-12-15 23:26:40.000000000 -0500
+++ volser/vos.c	2006-06-28 13:05:13.000000000 -0400
@@ -1080,7 +1080,7 @@
     fprintf(STDOUT, "dayUse\t\t%u\n", pntr->dayUse);
     fprintf(STDOUT, "weekUse\t\t%lu\t(Optional)\n", pntr->spare1);
     fprintf(STDOUT, "spare2\t\t%lu\t(Optional)\n", pntr->spare2);
-    fprintf(STDOUT, "spare3\t\t%lu\t(Optional)\n", pntr->spare3);
+    fprintf(STDOUT, "volIsShadow\t%s\t(Optional)\n", pntr->spare3 ? "Y" : "N");
     return;
 }
 
@@ -2487,7 +2487,7 @@
 	}
     }
 
-    flags = RV_NOVLDB;
+    flags = RV_NOVLDB | RV_SETSHADOW;
     if (as->parms[7].items) flags |= RV_OFFLINE;
     if (as->parms[8].items) flags |= RV_RDONLY;
     if (as->parms[9].items) flags |= RV_NOCLONE;
@@ -3672,6 +3672,7 @@
     afs_int32 pnum = 0, code;	/* part name */
     char part[10];
     int flags = 0;
+    int forceshadows = 0;
     char *volname = 0;
 
     tserver = 0;
@@ -3709,17 +3710,21 @@
 	}
     }
 
+    if (as->parms[3].items) {
+	forceshadows = 1;
+    }
+
     if (as->parms[2].items) {
 	/* Synchronize an individual volume */
 	volname = as->parms[2].items->data;
-	code = UV_SyncVolume(tserver, pnum, volname, flags);
+	code = UV_SyncVolume2(tserver, pnum, volname, flags, forceshadows);
     } else {
 	if (!tserver) {
 	    fprintf(STDERR,
 		    "Without a -volume option, the -server option is required\n");
 	    exit(1);
 	}
-	code = UV_SyncVldb(tserver, pnum, flags, 0 /*unused */ );
+	code = UV_SyncVldb(tserver, pnum, flags, forceshadows );
     }
 
     if (code) {
@@ -5873,6 +5878,8 @@
     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_OPTIONAL, "machine name");
     cmd_AddParm(ts, "-partition", CMD_SINGLE, CMD_OPTIONAL, "partition name");
     cmd_AddParm(ts, "-volume", CMD_SINGLE, CMD_OPTIONAL, "volume name or ID");
+    cmd_AddParm(ts, "-forceshadows", CMD_FLAG, CMD_OPTIONAL,
+		"add shadows to VLDB");
     COMMONPARMS;
 
     ts = cmd_CreateSyntax("syncserv", SyncServer, 0,
diff -u volser/vsprocs.c volser/vsprocs.c
--- volser/vsprocs.c	2006-01-24 22:49:53.000000000 -0500
+++ volser/vsprocs.c	2006-07-06 11:38:08.000000000 -0400
@@ -171,7 +171,10 @@
 				   void *cookie, manyResults * results);
 static afs_int32 CheckVolume(volintInfo * volumeinfo, afs_int32 aserver,
 			     afs_int32 apart, afs_int32 * modentry,
-			     afs_uint32 * maxvolid);
+			     afs_uint32 * maxvolid,
+			     struct rx_connection *aconn);
+static afs_int32 ClearShadow(struct rx_connection *aconn,
+				afs_int32 avol, afs_int32 apart);
 
 
 /*map the partition <partId> into partition name <partName>*/
@@ -2019,6 +2022,8 @@
  *     RV_CPINCR  - do incremental dump if target exists
  *     RV_NOVLDB  - don't create/update VLDB entry
  *     RV_NOCLONE - don't use a copy clone
+ *     RV_SETSHADOW -set tag so we don't sync by mistake
+ *     RV_CLRSHADOW -clear tag so shadow is treated as a normal RW
  */
 int
 UV_CopyVolume2(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
@@ -2050,6 +2055,7 @@
     error = 0;
     pntg = 0;
     newVol = 0;
+    cloneVol = 0;
 
     /* support control-c processing */
     if (setjmp(env))
@@ -2071,13 +2077,19 @@
     /* check if we can shortcut and use a local clone instead of a full copy */
     if (afromserver == atoserver && afrompart == atopart) {
 	justclone = 1;
+	if (atovolid) {
+	    fprintf(STDOUT,
+		    "Shadowing volume %u onto itself not allowed\n",
+		    atovolid);
+	    fflush(STDOUT);
+	    goto mfail;
+	}
     }
 
     /* ***
      * clone the read/write volume locally.
      * ***/
 
-    cloneVol = 0;
     if (!(flags & RV_NOCLONE)) {
 	VPRINT1("Starting transaction on source volume %u ...", afromvol);
 	code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
@@ -2295,11 +2307,15 @@
 		      &cookie);
     EGOTO1(mfail, code,
 	   "Failed to do the%s dump from old site to new site\n",
-	   afromvol);
+	 (flags & RV_NOCLONE) ? "" : " incremental");
     VDONE;
 
     VPRINT1("Setting volume flags on destination volume %u ...", newVol);
     volflag = ((flags & RV_OFFLINE) ? VTOutOfService : 0);	/* off or on-line */
+    if (flags & RV_SETSHADOW)
+	volflag |= VTIsShadow;
+    if (flags & RV_CLRSHADOW)
+	volflag |= VTNotShadow;
     code = AFSVolSetFlags(toconn, totid, volflag);
     EGOTO(mfail, code,
 	  "Failed to set the flags to make destination volume online\n");
@@ -5223,7 +5239,8 @@
  */
 static afs_int32
 CheckVolume(volintInfo * volumeinfo, afs_int32 aserver, afs_int32 apart,
-	    afs_int32 * modentry, afs_uint32 * maxvolid)
+	    afs_int32 * modentry, afs_uint32 * maxvolid, struct
+	    rx_connection *aconn)
 {
     int idx, j;
     afs_int32 code, error = 0;
@@ -5231,6 +5248,7 @@
     char pname[10];
     int pass = 0, islocked = 0, createentry, addvolume, modified, mod;
     afs_int32 rwvolid;
+    afs_int32 volIsShadow;
 
     if (modentry)
 	*modentry = 0;
@@ -5595,7 +5613,7 @@
 	if (createentry) {
 	    code = VLDB_CreateEntry(&storeEntry);
 	    if (code) {
-		fprintf(STDOUT,
+		fprintf(STDERR,
 			"Could not create a VLDB entry for the volume %lu\n",
 			(unsigned long)rwvolid);
 		ERROR_EXIT(code);
@@ -5613,6 +5631,15 @@
 		ERROR_EXIT(code);
 	    }
 	}
+	volIsShadow = volumeinfo->spare3;
+	if (volIsShadow) {
+	    code = ClearShadow(aconn, volumeinfo->volid, apart);
+	    if (code) {
+		fprintf(STDERR, "Could not clear shadow flag for volume %u\n",
+			volumeinfo->volid);
+		ERROR_EXIT(code);
+	    }
+	}
 	if (modentry)
 	    *modentry = modified;
     } else if (pass == 2) {
@@ -5669,6 +5696,43 @@
     return 0;
 }
 
+static afs_int32
+ClearShadow(struct rx_connection *aconn, afs_int32 avol, afs_int32 apart)
+{
+    afs_int32 error = 0, tid = 0, rcode = 0;
+    register afs_int32 code = 0;
+
+    code = AFSVolTransCreate(aconn, avol, apart, ITOffline, &tid);
+    if (code) {
+	fprintf(STDERR, "Failed to start a transaction on the shadow volume %u\n",
+	    avol);
+	error = code;
+    }
+
+    if (!code) {
+	code = AFSVolSetFlags(aconn, tid, VTNotShadow);
+	if (code) {
+	    fprintf(STDERR, "Failed to set the flags on the shadow volume %u\n",
+		    avol);
+	    error = code;
+	}
+    }
+
+    if (tid) {
+	code = AFSVolEndTrans(aconn, tid, &rcode);
+	if (code || rcode) {
+	    fprintf(STDERR, "Failed to end the transaction on the shadow volume %u\n",
+		    avol);
+	    if (!error)
+		error = (code ? code : rcode);
+	}
+    }
+
+    return error;
+
+}
+
+
 /* UV_SyncVolume()
  *      Synchronise <aserver> <apart>(if flags = 1) <avolid>.
  *      Synchronize an individual volume against a sever and partition.
@@ -5676,7 +5740,7 @@
  *      if the volume exists on specified servers (similar to syncvldb).
  */
 int
-UV_SyncVolume(afs_int32 aserver, afs_int32 apart, char *avolname, int flags)
+UV_SyncVolume2(afs_int32 aserver, afs_int32 apart, char *avolname, int flags, int force)
 {
     struct rx_connection *aconn = 0;
     afs_int32 j, k, code, vcode, error = 0;
@@ -5687,6 +5751,7 @@
     struct partList PartList;
     afs_int32 pcnt, rv;
     afs_int32 maxvolid = 0;
+    afs_int32 volIsShadow;
 
     volumeInfo.volEntries_val = (volintInfo *) 0;
     volumeInfo.volEntries_len = 0;
@@ -5768,14 +5833,24 @@
 			ERROR_EXIT(code);
 		    }
 		} else {
-		    /* Found one, sync it with VLDB entry */
-		    code =
-			CheckVolume(volumeInfo.volEntries_val, aserver,
-				    PartList.partId[j], &mod, &maxvolid);
-		    if (code)
-			ERROR_EXIT(code);
-		    if (mod)
-			modified++;
+		    /* Found one */
+		    volIsShadow = volumeInfo.volEntries_val->spare3;
+		    if (volIsShadow && !force) {
+			if (tverbose) {
+			    fprintf(STDOUT,
+				"You must use -forceshadows to sync this volume to the VLDB.\n");
+			}
+		    } else {
+			/* sync it with VLDB entry */
+			code =
+			    CheckVolume(volumeInfo.volEntries_val,
+				    aserver, PartList.partId[j], &mod,
+				    &maxvolid, aconn);
+			if (code)
+			    ERROR_EXIT(code);
+			if (mod)
+			    modified++;
+		    }
 		}
 
 		if (volumeInfo.volEntries_val)
@@ -5821,7 +5896,8 @@
 		    /* Found one, sync it with VLDB entry */
 		    code =
 			CheckVolume(volumeInfo.volEntries_val, aserver,
-				    PartList.partId[k], &mod, &maxvolid);
+				    PartList.partId[k], &mod, &maxvolid,
+				    aconn);
 		    if (code)
 			ERROR_EXIT(code);
 		    if (mod)
@@ -5895,6 +5971,14 @@
     return error;
 }
 
+
+int
+UV_SyncVolume(afs_int32 aserver, afs_int32 apart, char *avolname, int flags)
+{
+    return UV_SyncVolume2(aserver, apart, avolname, flags, 0);
+}
+
+
 /* UV_SyncVldb()
  *      Synchronise vldb with the file server <aserver> and,
  *      optionally, <apart>.
@@ -5913,6 +5997,7 @@
     afs_int32 failures = 0, modifications = 0, tentries = 0;
     afs_int32 modified;
     afs_uint32 maxvolid = 0;
+    afs_int32 volIsShadow;
 
     volumeInfo.volEntries_val = (volintInfo *) 0;
     volumeInfo.volEntries_len = 0;
@@ -5968,13 +6053,21 @@
 		fflush(STDOUT);
 	    }
 
-	    code = CheckVolume(vi, aserver, apart, &modified, &maxvolid);
-	    if (code) {
-		PrintError("", code);
-		failures++;
-		pfail++;
-	    } else if (modified) {
-		modifications++;
+	    volIsShadow = vi->spare3;
+	    if (volIsShadow && !force) {
+		if (verbose) {
+		    fprintf(STDOUT,
+			"You must use -forceshadows to sync this volume to the VLDB.\n");
+		}
+	    } else {
+		/* sync it with VLDB entry */
+		code = CheckVolume(vi, aserver, apart, &modified, &maxvolid, aconn);
+		if (code) {
+		    PrintError("", code);
+		    failures++;
+		    pfail++;
+		} else if (modified)
+		    modifications++;
 	    }
 
 	    if (verbose) {
-------------------------------------------------------------------------
The following fixes a bug in the UV_CopyVolume2 cleanup code.  Without
this patch, the cleanup code will delete the source volume.

Thanks.
========
diff -u volser/vsprocs.c volser/vsprocs.c
--- volser/vsprocs.c    2007-03-09 16:53:45.000000000 -0500
+++ volser/vsprocs.c    2007-03-14 16:10:14.000000000 -0400
@@ -2496,7 +2496,7 @@
	VPRINT1("Recovery: Creating transaction on clone volume %u ...",
		cloneVol);
	code =
-	    AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline,
+	    AFSVolTransCreate(fromconn, cloneVol, afrompart, ITOffline,
			      &clonetid);
	if (!code) {
	    VDONE;