/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
- *
+ *
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
#include <afsconfig.h>
#include <afs/param.h>
-RCSID
- ("$Header$");
+#include <roken.h>
-#include <sys/types.h>
-#include <stdio.h>
-#ifdef AFS_PTHREAD_ENV
-#include <assert.h>
-#else /* AFS_PTHREAD_ENV */
-#include <afs/assert.h>
-#endif /* AFS_PTHREAD_ENV */
#ifdef AFS_NT40_ENV
-#include <fcntl.h>
#include <windows.h>
#include <winbase.h>
-#include <io.h>
-#include <time.h>
-#else
-#include <sys/file.h>
-#include <sys/time.h>
#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
-#include <errno.h>
-#include <sys/stat.h>
#include <rx/xdr.h>
#include <afs/afsint.h>
+#include <afs/afssyscalls.h>
+
#include "nfs.h"
#include "lwp.h"
#include "lock.h"
-#include <afs/afssyscalls.h>
#include "ihandle.h"
#include "vnode.h"
#include "volume.h"
#include "partition.h"
#include "viceinode.h"
+#include "vol_prototypes.h"
+#include "common.h"
-/*@printflike@*/ extern void Log(const char *format, ...);
-
-int (*vol_PollProc) () = 0; /* someone must init this */
+int (*vol_PollProc) (void) = 0; /* someone must init this */
-#define ERROR_EXIT(code) {error = code; goto error_exit;}
+#define ERROR_EXIT(code) do { \
+ error = code; \
+ goto error_exit; \
+} while (0)
/* parameters for idec call - this could just be an IHandle_t, but leaving
* open the possibility of decrementing the special files as well.
struct clone_items *last;
};
-void CloneVolume();
-void CloneVolume_r();
+void CloneVolume(Error *, Volume *, Volume *, Volume *);
static int
ci_AddItem(struct clone_head *ah, Inode aino)
{
- register struct clone_items *ti;
+ struct clone_items *ti;
/* if no last elt (first call) or last item full, get a new one */
if ((!ah->last) || ah->last->nitems >= CLONE_MAXITEMS) {
ti = (struct clone_items *)malloc(sizeof(struct clone_items));
if (!ti) {
Log("ci_AddItem: malloc failed\n");
- assert(0);
+ osi_Panic("ci_AddItem: malloc failed\n");
}
ti->nitems = 0;
ti->next = (struct clone_items *)0;
/* apply a function to all dudes in the set */
int
-ci_Apply(struct clone_head *ah, int (*aproc) (), char *arock)
+ci_Apply(struct clone_head *ah, int (*aproc) (Inode, void *), void *arock)
{
- register struct clone_items *ti;
- register int i;
+ struct clone_items *ti;
+ int i;
for (ti = ah->first; ti; ti = ti->next) {
for (i = 0; i < ti->nitems; i++) {
int
ci_Destroy(struct clone_head *ah)
{
- register struct clone_items *ti, *ni;
+ struct clone_items *ti, *ni;
for (ti = ah->first; ti; ti = ni) {
ni = ti->next; /* guard against freeing */
}
static int
-IDecProc(Inode adata, struct clone_rock *aparm)
+IDecProc(Inode adata, void *arock)
{
+ struct clone_rock *aparm = (struct clone_rock *)arock;
IH_DEC(aparm->h, adata, aparm->vol);
DOPOLL;
return 0;
char buf[SIZEOF_LARGEDISKVNODE], dbuf[SIZEOF_LARGEDISKVNODE];
struct VnodeDiskObject *rwvnode = (struct VnodeDiskObject *)buf;
struct VnodeDiskObject *clvnode = (struct VnodeDiskObject *)dbuf;
- Inode rwinode, clinode;
+ Inode rwinode = 0;
+ Inode clinode;
struct clone_head decHead;
struct clone_rock decRock;
- afs_int32 offset, dircloned, inodeinced;
+ afs_foff_t offset = 0;
+ afs_int32 dircloned, inodeinced;
+ afs_int32 filecount = 0, diskused = 0;
+ afs_ino_str_t stmp;
struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
- int ReadWriteOriginal = VolumeWriteable(rwvp);
- struct DiskPartition *partition = rwvp->partition;
- Device device = rwvp->device;
+ /*
+ * The fileserver's -readonly switch should make this false, but we
+ * have no useful way to know in the volserver.
+ * This doesn't make client data mutable.
+ */
+ int ReadWriteOriginal = 1;
+
+ /* Correct number of files in volume: this assumes indexes are always
+ cloned starting with vLarge */
+ if (ReadWriteOriginal && class != vLarge) {
+ filecount = V_filecount(rwvp);
+ diskused = V_diskused(rwvp);
+ }
+
+ /* Initialize list of inodes to nuke - must do this before any calls
+ * to ERROR_EXIT, as the error handler requires an initialised list
+ */
+ ci_InitHead(&decHead);
+ decRock.h = V_linkHandle(rwvp);
+ decRock.vol = V_parentId(rwvp);
/* Open the RW volume's index file and seek to beginning */
IH_COPY(rwH, rwvp->vnodeIndex[class].handle);
rwfile = FDH_FDOPEN(rwFd, ReadWriteOriginal ? "r+" : "r");
if (!rwfile)
ERROR_EXIT(EIO);
- STREAM_SEEK(rwfile, vcp->diskSize, 0); /* Will fail if no vnodes */
+ STREAM_ASEEK(rwfile, vcp->diskSize); /* Will fail if no vnodes */
/* Open the clone volume's index file and seek to beginning */
IH_COPY(clHout, clvp->vnodeIndex[class].handle);
clfileout = FDH_FDOPEN(clFdOut, "a");
if (!clfileout)
ERROR_EXIT(EIO);
- code = STREAM_SEEK(clfileout, vcp->diskSize, 0);
+ code = STREAM_ASEEK(clfileout, vcp->diskSize);
if (code)
ERROR_EXIT(EIO);
clfilein = FDH_FDOPEN(clFdIn, "r");
if (!clfilein)
ERROR_EXIT(EIO);
- STREAM_SEEK(clfilein, vcp->diskSize, 0); /* Will fail if no vnodes */
+ STREAM_ASEEK(clfilein, vcp->diskSize); /* Will fail if no vnodes */
}
- /* Initialize list of inodes to nuke */
- ci_InitHead(&decHead);
- decRock.h = V_linkHandle(rwvp);
- decRock.vol = V_parentId(rwvp);
-
/* Read each vnode in the old volume's index file */
for (offset = vcp->diskSize;
STREAM_READ(rwvnode, vcp->diskSize, 1, rwfile) == 1;
}
if (rwvnode->type != vNull) {
+ afs_fsize_t ll;
+
if (rwvnode->vnodeMagic != vcp->magic)
ERROR_EXIT(-1);
rwinode = VNDISK_GET_INO(rwvnode);
+ filecount++;
+ VNDISK_GET_LEN(ll, rwvnode);
+ diskused += nBlocks(ll);
/* Increment the inode if not already */
if (clinode && (clinode == rwinode)) {
} else if (rwinode) {
if (IH_INC(V_linkHandle(rwvp), rwinode, V_parentId(rwvp)) ==
-1) {
- Log("IH_INC failed: %x, %s, %u errno %d\n",
- V_linkHandle(rwvp), PrintInode(NULL, rwinode),
+ Log("IH_INC failed: %"AFS_PTR_FMT", %s, %u errno %d\n",
+ V_linkHandle(rwvp), PrintInode(stmp, rwinode),
V_parentId(rwvp), errno);
- assert(0);
+ VForceOffline(rwvp);
+ ERROR_EXIT(EIO);
}
inodeinced = 1;
}
/* If a directory, mark vnode in old volume as cloned */
if ((rwvnode->type == vDirectory) && ReadWriteOriginal) {
#ifdef DVINC
- /*
+ /*
* It is my firmly held belief that immediately after
* copy-on-write, the two directories can be identical.
* If the new copy is changed (presumably, that is the very
rwvnode->dataVersion++;
#endif /* DVINC */
rwvnode->cloned = 1;
- code = STREAM_SEEK(rwfile, offset, 0);
+ code = STREAM_ASEEK(rwfile, offset);
if (code == -1)
goto clonefailed;
code = STREAM_WRITE(rwvnode, vcp->diskSize, 1, rwfile);
if (code != 1)
goto clonefailed;
dircloned = 1;
- code = STREAM_SEEK(rwfile, offset + vcp->diskSize, 0);
+ code = STREAM_ASEEK(rwfile, offset + vcp->diskSize);
if (code == -1)
goto clonefailed;
#ifdef DVINC
if (inodeinced) {
if (IH_DEC(V_linkHandle(rwvp), rwinode, V_parentId(rwvp)) ==
-1) {
- Log("IH_DEC failed: %x, %s, %u errno %d\n",
- V_linkHandle(rwvp), PrintInode(NULL, rwinode),
+ Log("IH_DEC failed: %"AFS_PTR_FMT", %s, %u errno %d\n",
+ V_linkHandle(rwvp), PrintInode(stmp, rwinode),
V_parentId(rwvp), errno);
- assert(0);
+ VForceOffline(rwvp);
+ ERROR_EXIT(EIO);
}
}
/* And if the directory was marked clone, unmark it */
if (dircloned) {
rwvnode->cloned = 0;
- if (STREAM_SEEK(rwfile, offset, 0) != -1)
- STREAM_WRITE(rwvnode, vcp->diskSize, 1, rwfile);
+ if (STREAM_ASEEK(rwfile, offset) != -1)
+ (void)STREAM_WRITE(rwvnode, vcp->diskSize, 1, rwfile);
}
ERROR_EXIT(EIO);
}
/* Clean out any junk at end of clone file */
if (reclone) {
- STREAM_SEEK(clfilein, offset, 0);
+ STREAM_ASEEK(clfilein, offset);
while (STREAM_READ(clvnode, vcp->diskSize, 1, clfilein) == 1) {
if (clvnode->type != vNull && VNDISK_GET_INO(clvnode) != 0) {
ci_AddItem(&decHead, VNDISK_GET_INO(clvnode));
error = FDH_TRUNC(rwFd, offset);
}
}
- FDH_SYNC(rwFd);
+ (void)FDH_SYNC(rwFd);
FDH_CLOSE(rwFd);
}
error = code;
ci_Destroy(&decHead);
+ if (ReadWriteOriginal && filecount > 0)
+ V_filecount(rwvp) = filecount;
+ if (ReadWriteOriginal && diskused > 0)
+ V_diskused(rwvp) = diskused;
return error;
}
void
-CloneVolume(Error * error, Volume * original, Volume * new, Volume * old)
-{
- VOL_LOCK CloneVolume_r(error, original, new, old);
-VOL_UNLOCK}
-
-void
-CloneVolume_r(Error * rerror, Volume * original, Volume * new, Volume * old)
+CloneVolume(Error * rerror, Volume * original, Volume * new, Volume * old)
{
afs_int32 code, error = 0;
afs_int32 reclone;
+ afs_int32 filecount = V_filecount(original), diskused = V_diskused(original);
*rerror = 0;
reclone = ((new == old) ? 1 : 0);
code = DoCloneIndex(original, new, vSmall, reclone);
if (code)
ERROR_EXIT(code);
+ if (filecount != V_filecount(original) || diskused != V_diskused(original))
+ Log("Clone %u: filecount %d -> %d diskused %d -> %d\n",
+ V_id(original), filecount, V_filecount(original), diskused, V_diskused(original));
- code = CopyVolumeHeader_r(&V_disk(original), &V_disk(new));
+ code = CopyVolumeHeader(&V_disk(original), &V_disk(new));
if (code)
ERROR_EXIT(code);