vol: Log ignored dirs that look like partitions
[openafs.git] / src / vol / partition.c
index 7a10874..d3f0a80 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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
@@ -31,6 +31,7 @@
 #else
 #include <sys/param.h>
 #include <sys/types.h>
+#include <unistd.h>
 
 #if AFS_HAVE_STATVFS || AFS_HAVE_STATVFS64
 #include <sys/statvfs.h>
 #include "lwp.h"
 #include <afs/afssyscalls.h>
 #include "ihandle.h"
+#include "common.h"
 #ifdef AFS_NAMEI_ENV
 #ifdef AFS_NT40_ENV
 #include "ntops.h"
 
 #endif /* !O_LARGEFILE */
 
-/*@printflike@*/ extern void Log(const char *format, ...);
-
 int aixlow_water = 8;          /* default 8% */
 struct DiskPartition64 *DiskPartitionList;
 
 #ifdef AFS_DEMAND_ATTACH_FS
+/* file to lock to conceptually "lock" the vol headers on a partition */
+#define AFS_PARTLOCK_FILE ".volheaders.lock"
+#define AFS_VOLUMELOCK_FILE ".volume.lock"
+
 static struct DiskPartition64 *DiskPartitionTable[VOLMAXPARTS+1];
 
 static struct DiskPartition64 * VLookupPartition_r(char * path);
 static void AddPartitionToTable_r(struct DiskPartition64 *);
-static void DeletePartitionFromTable_r(struct DiskPartition64 *);
 #endif /* AFS_DEMAND_ATTACH_FS */
 
 #ifdef AFS_SGI_XFS_IOPS_ENV
@@ -240,6 +243,7 @@ static void
 VInitPartition_r(char *path, char *devname, Device dev)
 {
     struct DiskPartition64 *dp, *op;
+
     dp = (struct DiskPartition64 *)malloc(sizeof(struct DiskPartition64));
     /* Add it to the end, to preserve order when we print statistics */
     for (op = DiskPartitionList; op; op = op->next) {
@@ -283,6 +287,17 @@ VInitPartition_r(char *path, char *devname, Device dev)
     assert(pthread_cond_init(&dp->vol_list.cv, NULL) == 0);
     dp->vol_list.len = 0;
     dp->vol_list.busy = 0;
+    {
+       char lockpath[MAXPATHLEN+1];
+       afs_snprintf(lockpath, MAXPATHLEN, "%s/" AFS_PARTLOCK_FILE, dp->name);
+       lockpath[MAXPATHLEN] = '\0';
+       VLockFileInit(&dp->headerLockFile, lockpath);
+
+       afs_snprintf(lockpath, MAXPATHLEN, "%s/" AFS_VOLUMELOCK_FILE, dp->name);
+       lockpath[MAXPATHLEN] = '\0';
+       VLockFileInit(&dp->volLockFile, lockpath);
+    }
+    VDiskLockInit(&dp->headerLock, &dp->headerLockFile, 1);
 #endif /* AFS_DEMAND_ATTACH_FS */
 }
 
@@ -386,18 +401,34 @@ VCheckPartition(char *part, char *devname)
  * attached (return value 1), or only attached when it is a separately
  * mounted partition (return value 0).  For non-NAMEI environments, it
  * always returns 0.
+ *
+ * *awouldattach will be set to 1 if the given path at least looks like a vice
+ * partition (that is, if we return 0, the only thing preventing this partition
+ * from being attached is the existence of the AlwaysAttach file), or to 0
+ * otherwise. *awouldattach is set regardless of whether or not the partition
+ * should always be attached or not.
  */
 static int
-VIsAlwaysAttach(char *part)
+VIsAlwaysAttach(char *part, int *awouldattach)
 {
 #ifdef AFS_NAMEI_ENV
     struct afs_stat st;
     char checkfile[256];
     int ret;
+#endif /* AFS_NAMEI_ENV */
+
+    if (awouldattach) {
+       *awouldattach = 0;
+    }
 
+#ifdef AFS_NAMEI_ENV
     if (strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE))
        return 0;
 
+    if (awouldattach) {
+       *awouldattach = 1;
+    }
+
     strncpy(checkfile, part, 100);
     strcat(checkfile, "/");
     strcat(checkfile, VICE_ALWAYSATTACH_FILE);
@@ -421,6 +452,7 @@ VAttachPartitions2(void)
     DIR *dirp;
     struct dirent *de;
     char pname[32];
+    int wouldattach;
 
     dirp = opendir("/");
     while ((de = readdir(dirp))) {
@@ -430,8 +462,31 @@ VAttachPartitions2(void)
 
        /* Only keep track of "/vicepx" partitions since automounter
         * may hose us */
-       if (VIsAlwaysAttach(pname))
+       if (VIsAlwaysAttach(pname, &wouldattach)) {
            VCheckPartition(pname, "");
+       } else {
+           struct afs_stat st;
+           if (wouldattach && VGetPartition(pname, 0) == NULL &&
+               afs_stat(pname, &st) == 0 && S_ISDIR(st.st_mode)) {
+
+               /* This is a /vicep* dir, and it has not been attached as a
+                * partition. This probably means that this is a /vicep* dir
+                * that is not a separate partition, so just give a notice so
+                * admins are not confused as to why their /vicep* dirs are not
+                * being attached.
+                *
+                * It is possible that the dir _is_ a separate partition and we
+                * failed to attach it earlier, making this message a bit
+                * confusing. But that should be rare, and an error message
+                * about the failure will already be logged right before this,
+                * so it should be clear enough. */
+
+               Log("VAttachPartitions: not attaching %s; either it is not a "
+                   "separate partition, or it failed to attach (create the "
+                   "file %s/" VICE_ALWAYSATTACH_FILE " to force attachment)\n",
+                   pname, pname);
+           }
+       }
     }
     closedir(dirp);
 #endif /* AFS_NAMEI_ENV */
@@ -463,11 +518,23 @@ VAttachPartitions(void)
 #endif
            || (strncmp(mnt.mnt_mntopts, "ro,ignore", 9) == 0))
            continue;
-       
+
        /* If we're going to always attach this partition, do it later. */
-       if (VIsAlwaysAttach(mnt.mnt_mountp))
+       if (VIsAlwaysAttach(mnt.mnt_mountp, NULL))
            continue;
 
+#ifndef AFS_NAMEI_ENV
+       if (hasmntopt(&mnt, "logging") != NULL) {
+           Log("This program is compiled without AFS_NAMEI_ENV, and "
+               "partition %s is mounted with the 'logging' option. "
+               "Using the inode fileserver backend with 'logging' UFS "
+               "partitions causes volume corruption, so please either "
+               "mount the partition without logging, or use the namei "
+               "fileserver backend. Aborting...\n", mnt.mnt_mountp);
+           errors++;
+       }
+#endif /* !AFS_NAMEI_ENV */
+
        if (VCheckPartition(mnt.mnt_mountp, mnt.mnt_special) < 0)
            errors++;
     }
@@ -498,7 +565,7 @@ VAttachPartitions(void)
            continue;
 
        /* If we're going to always attach this partition, do it later. */
-       if (VIsAlwaysAttach(mntent->mnt_dir))
+       if (VIsAlwaysAttach(mntent->mnt_dir, NULL))
            continue;
 
        if (VCheckPartition(mntent->mnt_dir, mntent->mnt_fsname) < 0)
@@ -518,10 +585,10 @@ VAttachPartitions(void)
  * (This function was grabbed from df.c)
  */
 int
-getmount(register struct vmount **vmountpp)
+getmount(struct vmount **vmountpp)
 {
     int size;
-    register struct vmount *vm;
+    struct vmount *vm;
     int nmounts;
 
     /* set initial size of mntctl buffer to a MAGIC NUMBER */
@@ -601,7 +668,7 @@ VAttachPartitions(void)
 #endif
 
        /* If we're going to always attach this partition, do it later. */
-       if (VIsAlwaysAttach(part))
+       if (VIsAlwaysAttach(part, NULL))
            continue;
 
        if (VCheckPartition(part, vmt2dataptr(vmountp, VMT_OBJECT)) < 0)
@@ -631,7 +698,7 @@ VAttachPartitions(void)
            continue;
 
        /* If we're going to always attach this partition, do it later. */
-       if (VIsAlwaysAttach(fsent->fs_file))
+       if (VIsAlwaysAttach(fsent->fs_file, NULL))
            continue;
 
        if (VCheckPartition(fsent->fs_file, fsent->fs_spec) < 0)
@@ -815,7 +882,7 @@ VAttachPartitions(void)
     }
     while ((mntent = getmntent(mfd))) {
        /* If we're going to always attach this partition, do it later. */
-       if (VIsAlwaysAttach(mntent->mnt_dir))
+       if (VIsAlwaysAttach(mntent->mnt_dir, NULL))
            continue;
 
        if (VCheckPartition(mntent->mnt_dir, mntent->mnt_fsname) < 0)
@@ -847,7 +914,7 @@ VPartitionPath(struct DiskPartition64 *part)
 struct DiskPartition64 *
 VGetPartition_r(char *name, int abortp)
 {
-    register struct DiskPartition64 *dp;
+    struct DiskPartition64 *dp;
 #ifdef AFS_DEMAND_ATTACH_FS
     dp = VLookupPartition_r(name);
 #else /* AFS_DEMAND_ATTACH_FS */
@@ -873,7 +940,7 @@ VGetPartition(char *name, int abortp)
 
 #ifdef AFS_NT40_ENV
 void
-VSetPartitionDiskUsage_r(register struct DiskPartition64 *dp)
+VSetPartitionDiskUsage_r(struct DiskPartition64 *dp)
 {
     ULARGE_INTEGER free_user, total, free_total;
     int ufree, tot, tfree;
@@ -897,7 +964,7 @@ VSetPartitionDiskUsage_r(register struct DiskPartition64 *dp)
 
 #else
 void
-VSetPartitionDiskUsage_r(register struct DiskPartition64 *dp)
+VSetPartitionDiskUsage_r(struct DiskPartition64 *dp)
 {
     int bsize, code;
     afs_int64 totalblks, free, used, availblks;
@@ -963,7 +1030,7 @@ VSetPartitionDiskUsage_r(register struct DiskPartition64 *dp)
 #endif /* AFS_NT40_ENV */
 
 void
-VSetPartitionDiskUsage(register struct DiskPartition64 *dp)
+VSetPartitionDiskUsage(struct DiskPartition64 *dp)
 {
     VOL_LOCK;
     VSetPartitionDiskUsage_r(dp);
@@ -1064,12 +1131,17 @@ VPrintDiskStats_r(void)
 {
     struct DiskPartition64 *dp;
     for (dp = DiskPartitionList; dp; dp = dp->next) {
-       Log("Partition %s: %d available 1K blocks (minfree=%d), ", dp->name,
-           dp->totalUsable, dp->minFree);
-       if (dp->free < 0)
-           Log("overallocated by %d blocks\n", -dp->free);
-       else
-           Log("%d free blocks\n", dp->free);
+       if (dp->free < 0) {
+           Log("Partition %s: %"AFS_INT64_FMT
+               " available 1K blocks (minfree=%"AFS_INT64_FMT"), "
+               "overallocated by %"AFS_INT64_FMT" blocks\n", dp->name,
+               dp->totalUsable, dp->minFree, -dp->free);
+       } else {
+           Log("Partition %s: %"AFS_INT64_FMT
+               " available 1K blocks (minfree=%"AFS_INT64_FMT"), "
+               "%"AFS_INT64_FMT" free blocks\n", dp->name,
+               dp->totalUsable, dp->minFree, dp->free);
+       }
     }
 }
 
@@ -1102,7 +1174,7 @@ VLockPartition_r(char *name)
                            CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL);
        assert(dp->lock_fd != INVALID_FD);
 
-       memset((char *)&lap, 0, sizeof(lap));
+       memset(&lap, 0, sizeof(lap));
        rc = LockFileEx((HANDLE) dp->lock_fd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1,
                        0, &lap);
        assert(rc);
@@ -1112,12 +1184,12 @@ VLockPartition_r(char *name)
 void
 VUnlockPartition_r(char *name)
 {
-    register struct DiskPartition64 *dp = VGetPartition_r(name, 0);
+    struct DiskPartition64 *dp = VGetPartition_r(name, 0);
     OVERLAPPED lap;
 
     if (!dp)
        return;                 /* no partition, will fail later */
-    memset((char *)&lap, 0, sizeof(lap));
+    memset(&lap, 0, sizeof(lap));
 
     UnlockFileEx((HANDLE) dp->lock_fd, 0, 1, 0, &lap);
     CloseHandle((HANDLE) dp->lock_fd);
@@ -1135,7 +1207,7 @@ VUnlockPartition_r(char *name)
 void
 VLockPartition_r(char *name)
 {
-    register struct DiskPartition64 *dp = VGetPartition_r(name, 0);
+    struct DiskPartition64 *dp = VGetPartition_r(name, 0);
     char *partitionName;
     int retries, code;
     struct timeval pausing;
@@ -1177,7 +1249,11 @@ VLockPartition_r(char *name)
 #endif
 
     for (retries = 25; retries; retries--) {
-       dp->lock_fd = afs_open(partitionName, code);
+       if (code & O_CREAT)
+           dp->lock_fd = afs_open(partitionName, code, 0644);
+       else
+           dp->lock_fd = afs_open(partitionName, code);
+
        if (dp->lock_fd != -1)
            break;
        if (errno == ENOENT)
@@ -1238,7 +1314,7 @@ VLockPartition_r(char *name)
 void
 VUnlockPartition_r(char *name)
 {
-    register struct DiskPartition64 *dp = VGetPartition_r(name, 0);
+    struct DiskPartition64 *dp = VGetPartition_r(name, 0);
     if (!dp)
        return;                 /* no partition, will fail later */
     close(dp->lock_fd);
@@ -1265,6 +1341,47 @@ VUnlockPartition(char *name)
 
 #ifdef AFS_DEMAND_ATTACH_FS
 
+/* new-style partition locks; these are only to have some mutual exclusion
+ * between the VGC scanner and volume utilies creating/altering vol headers
+ */
+
+/**
+ * lock a partition's vol headers.
+ *
+ * @param[in] dp       the partition to lock
+ * @param[in] locktype READ_LOCK or WRITE_LOCK
+ *
+ * @return operation status
+ *  @retval 0 success
+ */
+int
+VPartHeaderLock(struct DiskPartition64 *dp, int locktype)
+{
+    int code;
+
+    /* block on acquiring the lock */
+    int nonblock = 0;
+
+    code = VGetDiskLock(&dp->headerLock, locktype, nonblock);
+    if (code) {
+       Log("VPartHeaderLock: error %d locking partititon %s\n", code,
+           VPartitionPath(dp));
+    }
+    return code;
+}
+
+/**
+ * unlock a partition's vol headers.
+ *
+ * @param[in] dp       the partition to unlock
+ * @param[in] locktype READ_LOCK or WRITE_LOCK
+ */
+void
+VPartHeaderUnlock(struct DiskPartition64 *dp, int locktype)
+{
+    VReleaseDiskLock(&dp->headerLock, locktype);
+}
+
 /* XXX not sure this will work on AFS_NT40_ENV
  * needs to be tested!
  */
@@ -1286,7 +1403,7 @@ VUnlockPartition(char *name)
  * @internal volume package internal use only
  */
 
-struct DiskPartition64 * 
+struct DiskPartition64 *
 VGetPartitionById_r(afs_int32 id, int abortp)
 {
     struct DiskPartition64 *dp = NULL;
@@ -1317,7 +1434,7 @@ VGetPartitionById_r(afs_int32 id, int abortp)
 struct DiskPartition64 *
 VGetPartitionById(afs_int32 id, int abortp)
 {
-    struct Diskpartition64 * dp;
+    struct DiskPartition64 * dp;
 
     VOL_LOCK;
     dp = VGetPartitionById_r(id, abortp);
@@ -1326,7 +1443,7 @@ VGetPartitionById(afs_int32 id, int abortp)
     return dp;
 }
 
-static struct DiskPartition64 * 
+static struct DiskPartition64 *
 VLookupPartition_r(char * path)
 {
     afs_int32 id = volutil_GetPartitionID(path);
@@ -1337,17 +1454,19 @@ VLookupPartition_r(char * path)
     return DiskPartitionTable[id];
 }
 
-static void 
+static void
 AddPartitionToTable_r(struct DiskPartition64 *dp)
 {
     assert(dp->index >= 0 && dp->index <= VOLMAXPARTS);
     DiskPartitionTable[dp->index] = dp;
 }
 
-static void 
+#if 0
+static void
 DeletePartitionFromTable_r(struct DiskPartition64 *dp)
 {
     assert(dp->index >= 0 && dp->index <= VOLMAXPARTS);
     DiskPartitionTable[dp->index] = NULL;
 }
+#endif
 #endif /* AFS_DEMAND_ATTACH_FS */