afs_int32 PctSpare;
extern afs_int32 implicitAdminRights;
extern afs_int32 readonlyServer;
+extern int CopyOnWrite_calls, CopyOnWrite_off0, CopyOnWrite_size0;
+extern afs_fsize_t CopyOnWrite_maxsize;
/*
* Externals used by the xstat code.
/* Is it still necessary to drop this? We hit the net, we should... */
H_UNLOCK;
- if (uclient)
+ if (uclient) {
hpr_End(uclient);
+ uclient = NULL;
+ }
code = hpr_Initialize(&uclient);
if (!code)
* disk.inodeNumber and cloned)
*/
#define COPYBUFFSIZE 8192
+#define MAXFSIZE (~(afs_fsize_t) 0)
static int
-CopyOnWrite(Vnode * targetptr, Volume * volptr)
+CopyOnWrite(Vnode * targetptr, Volume * volptr, afs_fsize_t off, afs_fsize_t len)
{
Inode ino, nearInode;
int rdlen;
DFlush(); /* just in case? */
VN_GET_LEN(size, targetptr);
+ if (size > off)
+ size -= off;
+ else
+ size = 0;
+ if (size > len)
+ size = len;
+
buff = (char *)malloc(COPYBUFFSIZE);
if (buff == NULL) {
return EIO;
newFdP = IH_OPEN(newH);
assert(newFdP != NULL);
+ FDH_SEEK(targFdP, off, SEEK_SET);
+ FDH_SEEK(newFdP, off, SEEK_SET);
while (size > 0) {
if (size > COPYBUFFSIZE) { /* more than a buffer */
length = COPYBUFFSIZE;
return 0; /* success */
} /*CopyOnWrite */
+static int
+CopyOnWrite2(FdHandle_t *targFdP, FdHandle_t *newFdP, afs_fsize_t off, afs_fsize_t size) {
+ char *buff = (char *)malloc(COPYBUFFSIZE);
+ register int length;
+ int rdlen;
+ int wrlen;
+ int rc;
+
+ FDH_SEEK(targFdP, off, SEEK_SET);
+ FDH_SEEK(newFdP, off, SEEK_SET);
+
+ if (size > FDH_SIZE(targFdP) - off) size = FDH_SIZE(targFdP) - off;
+ while (size > 0) {
+ if (size > COPYBUFFSIZE) { /* more than a buffer */
+ length = COPYBUFFSIZE;
+ size -= COPYBUFFSIZE;
+ } else {
+ length = (int)size;
+ size = 0;
+ }
+ rdlen = FDH_READ(targFdP, buff, length);
+ if (rdlen == length)
+ wrlen = FDH_WRITE(newFdP, buff, length);
+ else
+ wrlen = 0;
+
+ if ((rdlen != length) || (wrlen != length)) {
+ /* no error recovery, at the worst we'll have a "hole" in the file */
+ rc = 1;
+ break;
+ }
+ }
+ free(buff);
+ return rc;
+}
+
/*
* Common code to handle with removing the Name (file when it's called from
return (EINVAL);
if (parentptr->disk.cloned) {
ViceLog(25, ("DeleteTarget : CopyOnWrite called\n"));
- if ((errorCode = CopyOnWrite(parentptr, volptr))) {
+ if ((errorCode = CopyOnWrite(parentptr, volptr, 0, MAXFSIZE))) {
ViceLog(20,
("DeleteTarget %s: CopyOnWrite failed %d\n", Name,
errorCode));
if (parentptr->disk.cloned) {
ViceLog(25, ("Alloc_NewVnode : CopyOnWrite called\n"));
- if ((errorCode = CopyOnWrite(parentptr, volptr))) { /* disk full */
+ if ((errorCode = CopyOnWrite(parentptr, volptr, 0, MAXFSIZE))) { /* disk full */
ViceLog(25, ("Alloc_NewVnode : CopyOnWrite failed\n"));
/* delete the vnode previously allocated */
(*targetptr)->delete = 1;
}
afs_int32
-SRXAFS_ResidencyCmd(struct rx_call * acall, struct AFSFid * Fid,
- struct ResidencyCmdInputs * Inputs,
- struct ResidencyCmdOutputs * Outputs)
+SRXAFS_FsCmd(struct rx_call * acall, struct AFSFid * Fid,
+ struct FsCmdInputs * Inputs,
+ struct FsCmdOutputs * Outputs)
{
- return EINVAL;
+ afs_int32 code = 0;
+ struct AFSCallBack callback;
+ struct AFSVolSync sync;
+
+ switch (Inputs->command) {
+ default:
+ code = EINVAL;
+ }
+ ViceLog(1,("FsCmd: cmd = %d, code=%d\n",
+ Inputs->command, Outputs->code));
+ return code;
}
#ifdef AFS_NT40_ENV
*/
if (oldvptr->disk.cloned) {
ViceLog(25, ("Rename : calling CopyOnWrite on old dir\n"));
- if ((errorCode = CopyOnWrite(oldvptr, volptr)))
+ if ((errorCode = CopyOnWrite(oldvptr, volptr, 0, MAXFSIZE)))
goto Bad_Rename;
}
SetDirHandle(&olddir, oldvptr);
if (newvptr->disk.cloned) {
ViceLog(25, ("Rename : calling CopyOnWrite on new dir\n"));
- if ((errorCode = CopyOnWrite(newvptr, volptr)))
+ if ((errorCode = CopyOnWrite(newvptr, volptr, 0, MAXFSIZE)))
goto Bad_Rename;
}
*/
if ((fileptr->disk.type == vDirectory) && (fileptr->disk.cloned)) {
ViceLog(25, ("Rename : calling CopyOnWrite on target dir\n"));
- if ((errorCode = CopyOnWrite(fileptr, volptr)))
+ if ((errorCode = CopyOnWrite(fileptr, volptr, 0, MAXFSIZE)))
goto Bad_Rename;
}
}
if (parentptr->disk.cloned) {
ViceLog(25, ("Link : calling CopyOnWrite on target dir\n"));
- if ((errorCode = CopyOnWrite(parentptr, volptr)))
+ if ((errorCode = CopyOnWrite(parentptr, volptr, 0, MAXFSIZE)))
goto Bad_Link; /* disk full error */
}
afs_fsize_t NewLength; /* size after this store completes */
afs_sfsize_t adjustSize; /* bytes to call VAdjust... with */
int linkCount = 0; /* link count on inode */
- FdHandle_t *fdP;
+ afs_fsize_t CoW_off, CoW_len;
+ FdHandle_t *fdP, *origfdP = NULL;
struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
#if FS_STATS_DETAILED
* mechanisms (i.e. copy on write overhead.) Also the right size
* of the disk will be recorded...
*/
- FDH_CLOSE(fdP);
+ origfdP = fdP;
VN_GET_LEN(size, targetptr);
volptr->partition->flags &= ~PART_DONTUPDATE;
VSetPartitionDiskUsage(volptr->partition);
volptr->partition->flags |= PART_DONTUPDATE;
if ((errorCode = VDiskUsage(volptr, nBlocks(size)))) {
volptr->partition->flags &= ~PART_DONTUPDATE;
+ FDH_CLOSE(origfdP);
return (errorCode);
}
- ViceLog(25, ("StoreData : calling CopyOnWrite on target dir\n"));
- if ((errorCode = CopyOnWrite(targetptr, volptr))) {
+ CoW_len = (FileLength >= (Length + Pos)) ? FileLength - Length : Pos;
+ CopyOnWrite_calls++;
+ if (CoW_len == 0) CopyOnWrite_size0++;
+ if (Pos == 0) CopyOnWrite_off0++;
+ if (CoW_len > CopyOnWrite_maxsize) CopyOnWrite_maxsize = CoW_len;
+
+ ViceLog(1, ("StoreData : calling CopyOnWrite on vnode %lu.%lu (%s) off 0x%llx size 0x%llx\n",
+ V_id(volptr), targetptr->vnodeNumber, V_name(volptr), 0, Pos));
+ if ((errorCode = CopyOnWrite(targetptr, volptr, 0, Pos))) {
ViceLog(25, ("StoreData : CopyOnWrite failed\n"));
volptr->partition->flags &= ~PART_DONTUPDATE;
+ FDH_CLOSE(origfdP);
return (errorCode);
}
volptr->partition->flags &= ~PART_DONTUPDATE;
if (fdP == NULL) {
ViceLog(25,
("StoreData : Reopen after CopyOnWrite failed\n"));
+ FDH_CLOSE(origfdP);
return ENOENT;
}
}
AdjustDiskUsage(volptr, adjustSize,
adjustSize - SpareComp(volptr)))) {
FDH_CLOSE(fdP);
+ if (origfdP) FDH_CLOSE(origfdP);
return (errorCode);
}
* need to update the target vnode.
*/
targetptr->changed_newTime = 1;
+ if (origfdP && (bytesTransfered < Length)) /* Need to "finish" CopyOnWrite still */
+ CopyOnWrite2(origfdP, fdP, Pos + bytesTransfered, NewLength - Pos - bytesTransfered);
+ if (origfdP) FDH_CLOSE(origfdP);
FDH_CLOSE(fdP);
/* set disk usage to be correct */
VAdjustDiskUsage(&errorCode, volptr,
nBlocks(NewLength)), 0);
return errorCode;
}
+ if (origfdP) { /* finish CopyOnWrite */
+ if ( (CoW_off = Pos + Length) < NewLength) {
+ errorCode = CopyOnWrite2(origfdP, fdP, CoW_off, CoW_len = NewLength - CoW_off);
+ ViceLog(1, ("StoreData : CopyOnWrite2 on vnode %lu.%lu (%s) off 0x%llx size 0x%llx returns %d\n",
+ V_id(volptr), targetptr->vnodeNumber, V_name(volptr), CoW_off, CoW_len, errorCode));
+ }
+ FDH_CLOSE(origfdP);
+ }
FDH_CLOSE(fdP);
FT_GetTimeOfDay(&StopTime, 0);