#include <afsconfig.h>
#include <afs/param.h>
+#include <afs/stds.h>
+#include <roken.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
#ifdef AFS_SGI_ENV
#undef SHARED /* XXX */
#endif
-#ifdef AFS_NT40_ENV
-#include <fcntl.h>
-#else
-#include <sys/param.h>
-#include <sys/file.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <string.h>
-
-#ifndef AFS_LINUX20_ENV
+
+#ifdef HAVE_NET_IF_H
#include <net/if.h>
-#ifndef AFS_ARM_DARWIN_ENV
+#endif
+
+#ifdef HAVE_NETINET_IF_ETHER_H
#include <netinet/if_ether.h>
#endif
+
+#if !defined(AFS_SGI_ENV) && defined(HAVE_SYS_MAP_H)
+#include <sys/map.h>
+#endif
+
+#ifdef HAVE_SYS_STATFS_H
+#include <sys/statfs.h>
#endif
+
+#ifdef HAVE_SYS_LOCKF_H
+#include <sys/lockf.h>
#endif
+
+#ifdef HAVE_SYS_DK_H
+#include <sys/dk.h>
+#endif
+
#ifdef AFS_HPUX_ENV
/* included early because of name conflict on IOPEN */
#include <sys/inode.h>
#undef IOPEN
#endif
#endif /* AFS_HPUX_ENV */
-#include <afs/stds.h>
+
#include <rx/xdr.h>
#include <afs/nfs.h>
#include <afs/afs_assert.h>
#include <afs/acl.h>
#include <rx/rx.h>
#include <rx/rx_globals.h>
-#include <sys/stat.h>
-#if ! defined(AFS_SGI_ENV) && ! defined(AFS_AIX32_ENV) && ! defined(AFS_NT40_ENV) && ! defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
-#include <sys/map.h>
-#endif
-#if !defined(AFS_NT40_ENV)
-#include <unistd.h>
-#endif
-#if !defined(AFS_SGI_ENV) && !defined(AFS_NT40_ENV)
-#ifdef AFS_AIX_ENV
-#include <sys/statfs.h>
-#include <sys/lockf.h>
-#else
-#if !defined(AFS_SUN5_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
-#include <sys/dk.h>
-#endif
-#endif
-#endif
+
#include <afs/cellconfig.h>
#include <afs/keys.h>
-#include <signal.h>
#include <afs/partition.h>
#include "viced_prototypes.h"
#include "viced.h"
pthread_mutex_t fileproc_glock_mutex;
#endif /* AFS_PTHREAD_ENV */
-#ifdef O_LARGEFILE
-#define afs_stat stat64
-#define afs_fstat fstat64
-#define afs_open open64
-#else /* !O_LARGEFILE */
-#define afs_stat stat
-#define afs_fstat fstat
-#define afs_open open
-#endif /* !O_LARGEFILE */
-
-
/* Useful local defines used by this module */
#define DONTCHECK 0
FS_UNLOCK;
} /*SetVolumeSync */
+/**
+ * Verify that the on-disk size for a vnode matches the length in the vnode
+ * index.
+ *
+ * @param[in] vp Volume pointer
+ * @param[in] vnp Vnode pointer
+ * @param[in] alen Size of the vnode on disk, if known. If unknown, give -1,
+ * and CheckLength itself will determine the on-disk size.
+ *
+ * @return operation status
+ * @retval 0 lengths match
+ * @retval nonzero Error; either the lengths do not match or there was an
+ * error determining the on-disk size. The volume should be
+ * taken offline and salvaged.
+ */
+static int
+CheckLength(struct Volume *vp, struct Vnode *vnp, afs_sfsize_t alen)
+{
+ afs_sfsize_t vlen;
+ VN_GET_LEN(vlen, vnp);
+
+ if (alen < 0) {
+ FdHandle_t *fdP;
+
+ fdP = IH_OPEN(vnp->handle);
+ if (fdP == NULL) {
+ ViceLog(0, ("CheckLength: cannot open inode for fid %lu.%lu.%lu\n",
+ afs_printable_uint32_lu(vp->hashid),
+ afs_printable_uint32_lu(Vn_id(vnp)),
+ afs_printable_uint32_lu(vnp->disk.uniquifier)));
+ return -1;
+ }
+ alen = FDH_SIZE(fdP);
+ FDH_CLOSE(fdP);
+ if (alen < 0) {
+ afs_int64 alen64 = alen;
+ ViceLog(0, ("CheckLength: cannot get size for inode for fid "
+ "%lu.%lu.%lu; FDH_SIZE returned %" AFS_INT64_FMT "\n",
+ afs_printable_uint32_lu(vp->hashid),
+ afs_printable_uint32_lu(Vn_id(vnp)),
+ afs_printable_uint32_lu(vnp->disk.uniquifier),
+ alen64));
+ return -1;
+ }
+ }
+
+ if (alen != vlen) {
+ afs_int64 alen64 = alen, vlen64 = vlen;
+ ViceLog(0, ("Fid %lu.%lu.%lu has inconsistent length (index "
+ "%lld inode %lld ); volume must be salvaged\n",
+ afs_printable_uint32_lu(vp->hashid),
+ afs_printable_uint32_lu(Vn_id(vnp)),
+ afs_printable_uint32_lu(vnp->disk.uniquifier),
+ vlen64, alen64));
+ return -1;
+ }
+ return 0;
+}
+
/*
* Note that this function always returns a held host, so
* that CallPostamble can block without the host's disappearing.
* are incremented and they must be eventualy released.
*/
static afs_int32
-CheckVnode(AFSFid * fid, Volume ** volptr, Vnode ** vptr, int lock)
+CheckVnodeWithCall(AFSFid * fid, Volume ** volptr, struct VCallByVol *cbv,
+ Vnode ** vptr, int lock)
{
Error fileCode = 0;
Error local_errorCode, errorCode = -1;
VRESTARTING
#endif
;
+#ifdef AFS_PTHREAD_ENV
+ static const struct timespec timeout_ts = { 0, 0 };
+ static const struct timespec * const ts = &timeout_ts;
+#else
+ static const struct timespec * const ts = NULL;
+#endif
errorCode = 0;
- *volptr = VGetVolumeNoWait(&local_errorCode, &errorCode, (afs_int32) fid->Volume);
+ *volptr = VGetVolumeWithCall(&local_errorCode, &errorCode,
+ fid->Volume, ts, cbv);
if (!errorCode) {
osi_Assert(*volptr);
break;
return (0);
} /*CheckVnode */
+static_inline afs_int32
+CheckVnode(AFSFid * fid, Volume ** volptr, Vnode ** vptr, int lock)
+{
+ return CheckVnodeWithCall(fid, volptr, NULL, vptr, lock);
+}
+
/*
* This routine returns the ACL associated with the targetptr. If the
* targetptr isn't a directory, we access its parent dir and get the ACL
* interface calls.
*/
static afs_int32
-GetVolumePackage(struct rx_connection *tcon, AFSFid * Fid, Volume ** volptr,
- Vnode ** targetptr, int chkforDir, Vnode ** parent,
- struct client **client, int locktype, afs_int32 * rights,
- afs_int32 * anyrights)
+GetVolumePackageWithCall(struct rx_connection *tcon, struct VCallByVol *cbv,
+ AFSFid * Fid, Volume ** volptr, Vnode ** targetptr,
+ int chkforDir, Vnode ** parent, struct client **client,
+ int locktype, afs_int32 * rights, afs_int32 * anyrights)
{
struct acl_accessList *aCL; /* Internal access List */
int aCLSize; /* size of the access list */
Error errorCode = 0; /* return code to caller */
- if ((errorCode = CheckVnode(Fid, volptr, targetptr, locktype)))
+ if ((errorCode = CheckVnodeWithCall(Fid, volptr, cbv, targetptr, locktype)))
return (errorCode);
if (chkforDir) {
if (chkforDir == MustNOTBeDIR
} /*GetVolumePackage */
+static_inline afs_int32
+GetVolumePackage(struct rx_connection *tcon, AFSFid * Fid, Volume ** volptr,
+ Vnode ** targetptr, int chkforDir, Vnode ** parent,
+ struct client **client, int locktype, afs_int32 * rights,
+ afs_int32 * anyrights)
+{
+ return GetVolumePackageWithCall(tcon, NULL, Fid, volptr, targetptr,
+ chkforDir, parent, client, locktype,
+ rights, anyrights);
+}
+
/*
* This is the opposite of GetVolumePackage(), and is always used at the end of
* AFS calls to put back all used vnodes and the volume in the proper order!
*/
static void
-PutVolumePackage(Vnode * parentwhentargetnotdir, Vnode * targetptr,
- Vnode * parentptr, Volume * volptr, struct client **client)
+PutVolumePackageWithCall(Vnode * parentwhentargetnotdir, Vnode * targetptr,
+ Vnode * parentptr, Volume * volptr,
+ struct client **client, struct VCallByVol *cbv)
{
Error fileCode = 0; /* Error code returned by the volume package */
osi_Assert(!fileCode || (fileCode == VSALVAGE));
}
if (volptr) {
- VPutVolume(volptr);
+ VPutVolumeWithCall(volptr, cbv);
}
if (*client) {
PutClient(client);
}
} /*PutVolumePackage */
+static_inline void
+PutVolumePackage(Vnode * parentwhentargetnotdir, Vnode * targetptr,
+ Vnode * parentptr, Volume * volptr, struct client **client)
+{
+ PutVolumePackageWithCall(parentwhentargetnotdir, targetptr, parentptr,
+ volptr, client, NULL);
+}
+
static int
VolumeOwner(struct client *client, Vnode * targetptr)
{
} else { /* file */
/* must have read access, or be owner and have insert access */
if (!(rights & PRSFS_READ)
- && !(OWNSp(client, targetptr) && (rights & PRSFS_INSERT)))
+ && !((OWNSp(client, targetptr) && (rights & PRSFS_INSERT)
+ && (client->ViceId != AnonymousID))))
return (EACCES);
}
if (CallingRoutine == CHK_FETCHDATA
/* watch for invalid names */
if (!strcmp(Name, ".") || !strcmp(Name, ".."))
return (EINVAL);
+
+ if (CheckLength(volptr, parentptr, -1)) {
+ VTakeOffline(volptr);
+ return VSALVAGE;
+ }
+
if (parentptr->disk.cloned) {
ViceLog(25, ("DeleteTarget : CopyOnWrite called\n"));
if ((errorCode = CopyOnWrite(parentptr, volptr, 0, MAXFSIZE))) {
AdjustDiskUsage(volptr, BlocksPreallocatedForVnode,
BlocksPreallocatedForVnode))) {
ViceLog(25,
- ("Insufficient space to allocate %" AFS_INT64_FMT " blocks\n",
+ ("Insufficient space to allocate %lld blocks\n",
(afs_intmax_t) BlocksPreallocatedForVnode));
return (errorCode);
}
+ if (CheckLength(volptr, parentptr, -1)) {
+ VAdjustDiskUsage(&temp, volptr, -BlocksPreallocatedForVnode, 0);
+ VTakeOffline(volptr);
+ return VSALVAGE;
+ }
+
*targetptr = VAllocVnode(&errorCode, volptr, FileType);
if (errorCode != 0) {
VAdjustDiskUsage(&temp, volptr, -BlocksPreallocatedForVnode, 0);
temp = strlen(V_name(volptr)) + 1;
*name = malloc(temp);
if (!*name) {
- ViceLog(0, ("Failed malloc in RXGetVolumeStatus\n"));
- osi_Panic("Failed malloc in RXGetVolumeStatus\n");
+ ViceLogThenPanic(0, ("Failed malloc in RXGetVolumeStatus\n"));
}
strcpy(*name, V_name(volptr));
temp = strlen(V_offlineMessage(volptr)) + 1;
*offMsg = malloc(temp);
if (!*offMsg) {
- ViceLog(0, ("Failed malloc in RXGetVolumeStatus\n"));
- osi_Panic("Failed malloc in RXGetVolumeStatus\n");
+ ViceLogThenPanic(0, ("Failed malloc in RXGetVolumeStatus\n"));
}
strcpy(*offMsg, V_offlineMessage(volptr));
#if OPENAFS_VOL_STATS
*motd = malloc(1);
if (!*motd) {
- ViceLog(0, ("Failed malloc in RXGetVolumeStatus\n"));
- osi_Panic("Failed malloc in RXGetVolumeStatus\n");
+ ViceLogThenPanic(0, ("Failed malloc in RXGetVolumeStatus\n"));
}
strcpy(*motd, nullString);
#else
temp = strlen(V_motd(volptr)) + 1;
*motd = malloc(temp);
if (!*motd) {
- ViceLog(0, ("Failed malloc in RXGetVolumeStatus\n"));
- osi_Panic("Failed malloc in RXGetVolumeStatus\n");
+ ViceLogThenPanic(0, ("Failed malloc in RXGetVolumeStatus\n"));
}
strcpy(*motd, V_motd(volptr));
#endif /* FS_STATS_DETAILED */
FS_UNLOCK;
tmp = malloc(sendBufSize);
if (!tmp) {
- ViceLog(0, ("Failed malloc in AllocSendBuffer\n"));
- osi_Panic("Failed malloc in AllocSendBuffer\n");
+ ViceLogThenPanic(0, ("Failed malloc in AllocSendBuffer\n"));
}
return tmp;
}
afs_int32 rights, anyrights; /* rights for this and any user */
struct client *t_client = NULL; /* tmp ptr to client data */
struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
+ struct VCallByVol tcbv, *cbv = NULL;
#if FS_STATS_DETAILED
struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
struct fs_stats_xferData *xferP; /* Ptr to this op's byte size struct */
("SRXAFS_FetchData, Fid = %u.%u.%u, Host %s:%d, Id %d\n",
Fid->Volume, Fid->Vnode, Fid->Unique, inet_ntoa(logHostAddr),
ntohs(rxr_PortOf(tcon)), t_client->ViceId));
+
+ queue_NodeInit(&tcbv);
+ tcbv.call = acall;
+ cbv = &tcbv;
+
/*
* Get volume/vnode for the fetched file; caller's access rights to
* it are also returned
*/
if ((errorCode =
- GetVolumePackage(tcon, Fid, &volptr, &targetptr, DONTCHECK,
+ GetVolumePackageWithCall(tcon, cbv, Fid, &volptr, &targetptr, DONTCHECK,
&parentwhentargetnotdir, &client, READ_LOCK,
&rights, &anyrights)))
goto Bad_FetchData;
Bad_FetchData:
/* Update and store volume/vnode and parent vnodes back */
- (void)PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0,
- volptr, &client);
+ (void)PutVolumePackageWithCall(parentwhentargetnotdir, targetptr,
+ (Vnode *) 0, volptr, &client, cbv);
ViceLog(2, ("SRXAFS_FetchData returns %d\n", errorCode));
errorCode = CallPostamble(tcon, errorCode, thost);
AccessList->AFSOpaque_len = 0;
AccessList->AFSOpaque_val = malloc(AFSOPAQUEMAX);
if (!AccessList->AFSOpaque_val) {
- ViceLog(0, ("Failed malloc in SRXAFS_FetchACL\n"));
- osi_Panic("Failed malloc in SRXAFS_FetchACL\n");
+ ViceLogThenPanic(0, ("Failed malloc in SRXAFS_FetchACL\n"));
}
/*
OutStats->AFSBulkStats_val = (struct AFSFetchStatus *)
malloc(nfiles * sizeof(struct AFSFetchStatus));
if (!OutStats->AFSBulkStats_val) {
- ViceLog(0, ("Failed malloc in SRXAFS_BulkStatus\n"));
- osi_Panic("Failed malloc in SRXAFS_BulkStatus\n");
+ ViceLogThenPanic(0, ("Failed malloc in SRXAFS_BulkStatus\n"));
}
OutStats->AFSBulkStats_len = nfiles;
CallBacks->AFSCBs_val = (struct AFSCallBack *)
malloc(nfiles * sizeof(struct AFSCallBack));
if (!CallBacks->AFSCBs_val) {
- ViceLog(0, ("Failed malloc in SRXAFS_BulkStatus\n"));
- osi_Panic("Failed malloc in SRXAFS_BulkStatus\n");
+ ViceLogThenPanic(0, ("Failed malloc in SRXAFS_BulkStatus\n"));
}
CallBacks->AFSCBs_len = nfiles;
OutStats->AFSBulkStats_val = (struct AFSFetchStatus *)
malloc(nfiles * sizeof(struct AFSFetchStatus));
if (!OutStats->AFSBulkStats_val) {
- ViceLog(0, ("Failed malloc in SRXAFS_FetchStatus\n"));
- osi_Panic("Failed malloc in SRXAFS_FetchStatus\n");
+ ViceLogThenPanic(0, ("Failed malloc in SRXAFS_FetchStatus\n"));
}
OutStats->AFSBulkStats_len = nfiles;
CallBacks->AFSCBs_val = (struct AFSCallBack *)
malloc(nfiles * sizeof(struct AFSCallBack));
if (!CallBacks->AFSCBs_val) {
- ViceLog(0, ("Failed malloc in SRXAFS_FetchStatus\n"));
- osi_Panic("Failed malloc in SRXAFS_FetchStatus\n");
+ ViceLogThenPanic(0, ("Failed malloc in SRXAFS_FetchStatus\n"));
}
CallBacks->AFSCBs_len = nfiles;
goto Bad_Rename;
}
+ if (CheckLength(volptr, oldvptr, -1) ||
+ CheckLength(volptr, newvptr, -1)) {
+ VTakeOffline(volptr);
+ errorCode = VSALVAGE;
+ goto Bad_Rename;
+ }
+
/* The CopyOnWrite might return ENOSPC ( disk full). Even if the second
* call to CopyOnWrite returns error, it is not necessary to revert back
* the effects of the first call because the contents of the volume is
goto Bad_Link;
}
+ if (CheckLength(volptr, parentptr, -1)) {
+ VTakeOffline(volptr);
+ errorCode = VSALVAGE;
+ goto Bad_Link;
+ }
+
/* get the file vnode */
if ((errorCode =
CheckVnode(ExistingFid, &volptr, &targetptr, WRITE_LOCK))) {
volptr->hashid));
return EIO;
}
+ if (CheckLength(volptr, targetptr, tlen)) {
+ FDH_CLOSE(fdP);
+ VTakeOffline(volptr);
+ return VSALVAGE;
+ }
if (Pos > tlen) {
Len = 0;
}
(*a_bytesFetchedP) += nBytes;
#endif /* FS_STATS_DETAILED */
if (nBytes != wlen) {
+ afs_int32 err;
FDH_CLOSE(fdP);
#ifndef HAVE_PIOV
FreeSendBuffer((struct afs_buffer *)tbuffer);
#endif /* HAVE_PIOV */
+ err = VIsGoingOffline(volptr);
+ if (err) {
+ return err;
+ }
return -31;
}
Len -= wlen;
lhp = IH_OPEN(V_linkHandle(vp));
if (!lhp)
return EIO;
-#ifdef AFS_NT40_ENV
- *lc = nt_GetLinkCount(lhp, fdP->fd_ih->ih_ino, 0);
-#else
- *lc = namei_GetLinkCount(lhp, fdP->fd_ih->ih_ino, 0);
-#endif
+ *lc = namei_GetLinkCount(lhp, fdP->fd_ih->ih_ino, 0, 0, 1);
FDH_CLOSE(lhp);
if (*lc < 0)
return -1;
volptr->hashid));
return EIO;
}
+ if (CheckLength(volptr, targetptr, DataLength)) {
+ FDH_CLOSE(fdP);
+ VTakeOffline(volptr);
+ return VSALVAGE;
+ }
if (linkCount != 1) {
afs_fsize_t size;
if (fdP == NULL) {
ViceLog(25,
("StoreData : Reopen after CopyOnWrite failed\n"));
- FDH_CLOSE(origfdP);
+ FDH_REALLYCLOSE(origfdP);
return ENOENT;
}
}
AdjustDiskUsage(volptr, adjustSize,
adjustSize - SpareComp(volptr)))) {
FDH_CLOSE(fdP);
- if (origfdP) FDH_CLOSE(origfdP);
+ if (origfdP) FDH_REALLYCLOSE(origfdP);
return (errorCode);
}
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);
+ if (origfdP) FDH_REALLYCLOSE(origfdP);
FDH_CLOSE(fdP);
/* set disk usage to be correct */
VAdjustDiskUsage(&errorCode, volptr,
afs_printable_VnodeId_u(targetptr->vnodeNumber),
V_name(volptr), CoW_off, CoW_len, errorCode));
}
- FDH_CLOSE(origfdP);
+ FDH_REALLYCLOSE(origfdP);
}
FDH_CLOSE(fdP);