vol-allocate-partition-names-dynamically-to-avoid-problems-with-vx-stuff-20020624
[openafs.git] / src / vol / partition.c
index 0ed0fa2..4b2f6e1 100644 (file)
@@ -7,8 +7,6 @@
  * directory or online at http://www.openafs.org/dl/license10.html
  */
 
-#ifndef lint
-#endif
 /*
 
        System:         VICE-TWO
 
  */
 
+#include <afsconfig.h>
 #include <afs/param.h>
+
+RCSID("$Header$");
+
 #include <ctype.h>
 #ifdef AFS_NT40_ENV
 #include <windows.h>
@@ -30,7 +32,7 @@
 #if AFS_HAVE_STATVFS
 #include <sys/statvfs.h>
 #endif /* AFS_HAVE_STATVFS */
-#if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
+#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
 #include <sys/mount.h>
 #endif
 
@@ -44,7 +46,7 @@
 #ifdef AFS_SUN5_ENV
 #include <sys/fs/ufs_fs.h>
 #else
-#if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
+#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
 #include <ufs/ufs/dinode.h>
 #include <ufs/ffs/fs.h>
 #else
@@ -52,7 +54,7 @@
 #endif
 #endif
 #else /* AFS_VFSINCL_ENV */
-#if !defined(AFS_AIX_ENV) && !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
+#if !defined(AFS_AIX_ENV) && !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
 #include <sys/fs.h>
 #endif
 #endif /* AFS_VFSINCL_ENV */
 #include "ntops.h"
 #else
 #include "namei_ops.h"
-#if defined(AFS_SGI_ENV)
-#include <sys/dir.h>
-#else
 #include <dirent.h>
-#endif /* AFS_SGI_ENV */
 #endif /* AFS_NT40_ENV */
 #endif /* AFS_NAMEI_ENV */
 #include "vnode.h"
@@ -192,16 +190,21 @@ static void VInitPartition_r(char *path, char *devname, Device dev)
     else
        DiskPartitionList = dp;
     dp->next = 0;
-    strcpy(dp->name, path);
+    dp->name = (char *)malloc(strlen(path) + 1);
+    strncpy(dp->name, path, strlen(path) + 1);
 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
-#ifdef AFS_SUN5_ENV
-    strcpy(dp->devName, devname);
-#else /* AFS_SUN5_ENV */
+    /* Create a lockfile for the partition, of the form /vicepa/Lock/vicepa */
+    dp->devName = (char *)malloc(2 * strlen(path) + 6);
     strcpy(dp->devName, path);
-#endif
+    strcat(dp->devName, "/");
+    strcat(dp->devName, "Lock");
+    mkdir(dp->devName, 0700);
+    strcat(dp->devName, path);
+    close(open(dp->devName, O_RDWR | O_CREAT, 0600));
     dp->device = volutil_GetPartitionID(path);
 #else
-    strcpy(dp->devName, devname);
+    dp->devName = (char *)malloc(strlen(devname) + 1);
+    strncpy(dp->devName, devname, strlen(devname) + 1);
     dp->device = dev;
 #endif
     dp->lock_fd = -1;
@@ -299,7 +302,7 @@ int VCheckPartition(part, devname)
        return -1;
 #endif
 
-#ifdef AFS_DUX40_ENV
+#if defined(AFS_DUX40_ENV) && !defined(AFS_NAMEI_ENV)
     if (status.st_ino != ROOTINO) {
        Log("%s is not a mounted file system; ignored.\n", part);
        return 0;
@@ -310,6 +313,59 @@ int VCheckPartition(part, devname)
 
     return 0;
 }
+
+/* VIsAlwaysAttach() checks whether a /vicepX directory should always be
+ * 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.
+ */
+static int VIsAlwaysAttach(part)
+    char *part;
+{
+#ifdef AFS_NAMEI_ENV
+    struct stat st;
+    char checkfile[256];
+    int ret;
+
+    if (strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE))
+       return 0;
+
+    strncpy(checkfile, part, 100);
+    strcat(checkfile, "/");
+    strcat(checkfile, VICE_ALWAYSATTACH_FILE);
+
+    ret = stat(checkfile, &st);
+    return (ret < 0) ? 0 : 1;
+#else  /* AFS_NAMEI_ENV */
+    return 0;
+#endif /* AFS_NAMEI_ENV */
+}
+
+/* VAttachPartitions2() looks for and attaches /vicepX partitions
+ * where a special file (VICE_ALWAYSATTACH_FILE) exists.  This is
+ * used to attach /vicepX directories which aren't on dedicated
+ * partitions, in the NAMEI fileserver.
+ */
+void VAttachPartitions2() {
+#ifdef AFS_NAMEI_ENV
+    DIR *dirp;
+    struct dirent *de;
+    char pname[32];
+
+    dirp = opendir("/");
+    while (de = readdir(dirp)) {
+       strcpy(pname, "/");
+       strncat(pname, de->d_name, 20);
+       pname[sizeof(pname)-1] = '\0';
+
+       /* Only keep track of "/vicepx" partitions since automounter
+          may hose us */
+       if (VIsAlwaysAttach(pname))
+           VCheckPartition(pname, "");
+    }
+    closedir(dirp);
+#endif /* AFS_NAMEI_ENV */
+}
 #endif /* AFS_NT40_ENV */
 
 #ifdef AFS_SUN5_ENV
@@ -330,11 +386,18 @@ int VAttachPartitions(void)
            (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))
+           continue;
+
        if (VCheckPartition(mnt.mnt_mountp, mnt.mnt_special) < 0 )
            errors ++;
     }
 
-   (void) fclose(mntfile);
+    (void) fclose(mntfile);
+
+    /* Process the always-attach partitions, if any. */
+    VAttachPartitions2();
 
     return errors ;
 }
@@ -354,12 +417,19 @@ int VAttachPartitions(void)
     while (mntent = getmntent(mfd)) {
        if (!hasmntopt(mntent, MNTOPT_RW)) continue;
        
+       /* If we're going to always attach this partition, do it later. */
+       if (VIsAlwaysAttach(mntent->mnt_dir))
+           continue;
+
        if (VCheckPartition(mntent->mnt_dir, mntent->mnt_fsname) < 0 )
            errors ++;
     }
 
     endmntent(mfd);
 
+    /* Process the always-attach partitions, if any. */
+    VAttachPartitions2();
+
     return errors ;
 }
 #endif
@@ -429,6 +499,7 @@ int VAttachPartitions(void)
            continue; /* Ignore any "special" partitions */
 
 #ifdef AFS_AIX42_ENV
+#ifndef AFS_NAMEI_ENV
        {
            struct superblock fs;
            /* The Log statements are non-sequiters in the SalvageLog and don't
@@ -446,15 +517,23 @@ int VAttachPartitions(void)
            }
        }
 #endif
+#endif
+
+       /* If we're going to always attach this partition, do it later. */
+       if (VIsAlwaysAttach(part))
+           continue;
 
        if (VCheckPartition(part, vmt2dataptr(vmountp, VMT_OBJECT)) < 0 )
            errors ++;
     }
-    return errors ;
 
+    /* Process the always-attach partitions, if any. */
+    VAttachPartitions2();
+
+    return errors ;
 }
 #endif
-#if defined(AFS_DUX40_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
+#if defined(AFS_DUX40_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
 int VAttachPartitions(void)
 {
     int errors = 0;
@@ -468,11 +547,18 @@ int VAttachPartitions(void)
     while (fsent = getfsent()) {
        if (strcmp(fsent->fs_type, "rw") != 0) continue;
 
+       /* If we're going to always attach this partition, do it later. */
+       if (VIsAlwaysAttach(fsent->fs_file))
+           continue;
+
        if (VCheckPartition(fsent->fs_file, fsent->fs_spec) < 0 )
            errors ++;
     }
     endfsent();
     
+    /* Process the always-attach partitions, if any. */
+    VAttachPartitions2();
+
     return errors ;
 }
 #endif
@@ -642,11 +728,18 @@ int VAttachPartitions(void)
        }
     }
     while (mntent = getmntent(mfd)) {
+       /* If we're going to always attach this partition, do it later. */
+       if (VIsAlwaysAttach(mntent->mnt_dir))
+           continue;
+
        if (VCheckPartition(mntent->mnt_dir, mntent->mnt_fsname) < 0 )
            errors ++;
     }
     endmntent(mfd);
 
+    /* Process the always-attach partitions, if any. */
+    VAttachPartitions2();
+
     return errors ;
 }
 #endif /* AFS_LINUX22_ENV */
@@ -801,7 +894,6 @@ void VResetDiskUsage(void)
 
 void VAdjustDiskUsage_r(Error *ec, Volume *vp, afs_int32 blocks, afs_int32 checkBlocks)
 {
-    afs_int32 rem, minavail;
     *ec = 0;
     /* why blocks instead of checkBlocks in the check below?  Otherwise, any check
        for less than BlocksSpare would skip the error-checking path, and we
@@ -809,6 +901,8 @@ void VAdjustDiskUsage_r(Error *ec, Volume *vp, afs_int32 blocks, afs_int32 check
        blocks. */
     if (blocks > 0) {
 #ifdef AFS_AIX32_ENV
+        afs_int32 rem, minavail;
+
        if ((rem = vp->partition->free - checkBlocks) < 
            (minavail = (vp->partition->totalUsable * aixlow_water) / 100))
 #else
@@ -831,9 +925,10 @@ void VAdjustDiskUsage(Error *ec, Volume *vp, afs_int32 blocks, afs_int32 checkBl
 
 int VDiskUsage_r(Volume *vp, afs_int32 blocks)
 {
-    afs_int32 rem, minavail;
     if (blocks > 0) {
 #ifdef AFS_AIX32_ENV
+        afs_int32 rem, minavail;
+
        if ((rem = vp->partition->free - blocks) < 
            (minavail = (vp->partition->totalUsable * aixlow_water) / 100))
 #else
@@ -932,12 +1027,22 @@ void VLockPartition_r(char *name)
     unsigned int       *globalMask;
     int                        globalMaskIndex;
 #endif /* defined(AFS_HPUX_ENV) */
+#ifdef AFS_NAMEI_ENV
+#ifdef AFS_AIX42_ENV
+    char LockFileName[MAXPATHLEN + 1];
+
+    sprintf((char *)&LockFileName, "%s/AFSINODE_FSLock", name);
+    partitionName = (char *) &LockFileName;
+#endif
+#endif
     
     if (!dp) return;   /* no partition, will fail later */
     if (dp->lock_fd != -1) return;
 
 #if    defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV)
+#if !defined(AFS_AIX42_ENV) || !defined(AFS_NAMEI_ENV)
     partitionName = dp->devName;
+#endif
     code = O_RDWR;
 #else
     partitionName = dp->name;
@@ -947,6 +1052,8 @@ void VLockPartition_r(char *name)
     for (retries=25; retries; retries--) {
         dp->lock_fd = open(partitionName, code);
         if (dp->lock_fd != -1) break;
+       if (errno == ENOENT)
+           code |= O_CREAT;
         pausing.tv_sec = 0;
         pausing.tv_usec = 500000;
         select(0, NULL, NULL, NULL, &pausing);
@@ -997,7 +1104,7 @@ void VLockPartition_r(char *name)
        assert (lockf(dp->lock_fd, F_LOCK, 0) != -1); 
 #else
        assert (flock(dp->lock_fd, LOCK_EX) == 0);
-#endif /* defined(AFS_AIX_ENV) */
+#endif /* defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) */
 #endif
 }