viced: Check vnode length on Rename and Link
[openafs.git] / src / viced / afsfileprocs.c
index 9ba8b88..b2dac04 100644 (file)
 
 #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>
@@ -62,7 +66,7 @@
 #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"
@@ -277,16 +264,56 @@ SetVolumeSync(struct AFSVolSync *async, Volume * avol)
     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 "
-                   "%" AFS_INT64_FMT ", inode %" AFS_INT64_FMT "); volume "
-                   "must be salvaged\n",
+                   "%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),
@@ -1368,6 +1395,12 @@ DeleteTarget(Vnode * parentptr, Volume * volptr, Vnode ** targetptr,
     /* watch for invalid names */
     if (!strcmp(Name, ".") || !strcmp(Name, ".."))
        return (EINVAL);
+
+    if (CheckLength(volptr, parentptr, -1)) {
+       VTakeOffline_r(volptr);
+       return VSALVAGE;
+    }
+
     if (parentptr->disk.cloned) {
        ViceLog(25, ("DeleteTarget : CopyOnWrite called\n"));
        if ((errorCode = CopyOnWrite(parentptr, volptr, 0, MAXFSIZE))) {
@@ -1774,11 +1807,17 @@ Alloc_NewVnode(Vnode * parentptr, DirHandle * dir, Volume * volptr,
         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_r(volptr);
+       return VSALVAGE;
+    }
+
     *targetptr = VAllocVnode(&errorCode, volptr, FileType);
     if (errorCode != 0) {
        VAdjustDiskUsage(&temp, volptr, -BlocksPreallocatedForVnode, 0);
@@ -1989,30 +2028,26 @@ RXGetVolumeStatus(AFSFetchVolumeStatus * status, char **name, char **offMsg,
     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 */
@@ -2101,8 +2136,7 @@ AllocSendBuffer(void)
        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;
     }
@@ -2478,8 +2512,7 @@ SRXAFS_FetchACL(struct rx_call * acall, struct AFSFid * Fid,
     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"));
     }
 
     /*
@@ -2668,15 +2701,13 @@ SRXAFS_BulkStatus(struct rx_call * acall, struct AFSCBFids * Fids,
     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;
 
@@ -2819,15 +2850,13 @@ SRXAFS_InlineBulkStatus(struct rx_call * acall, struct AFSCBFids * Fids,
     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;
 
@@ -3978,6 +4007,13 @@ SAFSS_Rename(struct rx_call *acall, struct AFSFid *OldDirFid, char *OldName,
        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
@@ -4668,6 +4704,12 @@ SAFSS_Link(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
        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))) {
@@ -7411,7 +7453,7 @@ StoreData_RXStyle(Volume * volptr, Vnode * targetptr, struct AFSFid * Fid,
            if (fdP == NULL) {
                ViceLog(25,
                        ("StoreData : Reopen after CopyOnWrite failed\n"));
-               FDH_CLOSE(origfdP);
+               FDH_REALLYCLOSE(origfdP);
                return ENOENT;
            }
        }
@@ -7443,7 +7485,7 @@ StoreData_RXStyle(Volume * volptr, Vnode * targetptr, struct AFSFid * Fid,
         AdjustDiskUsage(volptr, adjustSize,
                         adjustSize - SpareComp(volptr)))) {
        FDH_CLOSE(fdP);
-       if (origfdP) FDH_CLOSE(origfdP);
+       if (origfdP) FDH_REALLYCLOSE(origfdP);
        return (errorCode);
     }
 
@@ -7543,7 +7585,7 @@ StoreData_RXStyle(Volume * volptr, Vnode * targetptr, struct AFSFid * Fid,
        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,
@@ -7560,7 +7602,7 @@ StoreData_RXStyle(Volume * volptr, Vnode * targetptr, struct AFSFid * Fid,
                        afs_printable_VnodeId_u(targetptr->vnodeNumber),
                        V_name(volptr), CoW_off, CoW_len, errorCode));
        }
-       FDH_CLOSE(origfdP);
+       FDH_REALLYCLOSE(origfdP);
     }
     FDH_CLOSE(fdP);